Return Type | Function name | Arguments |
---|---|---|
void | hzIpServer::ServeX | (void) |
Declared in file: hzIpServer.h
Defined in file : hzIpServer.cpp
Function Logic:
Function body:
void hzIpServer::ServeX (void) { _hzfunc("hzIpServer::ServeX") ; hzMapS<uint32_t,hzIpListen*> ls ; hzMapS<uint32_t,hzIpConnex*> allCC ; hzMapS<uint32_t,hzIpConnex*> duff ; hzList<hzIpListen*>::Iter I ; struct epoll_event epEventNew ; hzPacket tbuf ; SOCKADDR cliAddr ; SOCKADDRIN cliAddrIn ; socklen_t cliLen ; hzIpListen* pLS ; hzIpConnex* pCC ; SSL* pSSL ; timeval tv ; pthread_attr_t tattr ; uint64_t nsThen ; uint64_t nsNow ; hzIpaddr ipa ; uint32_t nBannedAttempts ; uint32_t nCliSeq = 1; uint32_t nX ; uint32_t nSlot ; uint32_t nError ; uint32_t cSock ; uint32_t cPort ; int32_t aSock ; int32_t flags ; int32_t nC ; int32_t nRecv ; int32_t nEpollEvents ; int32_t sys_rc ; hzEcode err ; char ipbuf[44]; pthread_attr_init(&tattr) ; pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) ; s_epollSocket = epoll_create1(0); if (s_epollSocket == -1) Fatal("Could not create epoll socket\n") ; m_pLog->Log("Epoll socket is %d\n", s_epollSocket) ; for (I = m_LS ; I.Valid() ; I++) { pLS = I.Element() ; epEventNew.data.fd = pLS->GetSocket() ; epEventNew.events = EPOLLIN ; if (epoll_ctl(s_epollSocket, EPOLL_CTL_ADD, pLS->GetSocket(), &epEventNew) < 0) Fatal("Could not add listening socket %d to the epoll controller\n", pLS->GetSocket()) ; m_pLog->Log("Added listening socket is %d\n", pLS->GetSocket()) ; ls.Insert(pLS->GetSocket(), pLS) ; } m_nLoop = nCliSeq = nBannedAttempts = 0; for (;;) { nsThen = RealtimeNano() ; nEpollEvents = epoll_wait(s_epollSocket, m_arEvents, MAXEVENTS, 30000); nsNow = RealtimeNano() ; for (nC = 0; nC < nEpollEvents ; nC++) { if (_hzGlobal_Debug & HZ_DEBUG_SERVER) { if (nSlot) m_pLog->Log("Loop %u slot %u: Event on socket %d\n", m_nLoop, nSlot, m_arEvents[nSlot].data.fd) ; else m_pLog->Log("Loop %u: Waited %lu nanoseconds for %d events: 1st sock %u\n", m_nLoop, nsNow - nsThen, nEpollEvents, m_arEvents[0].data.fd); } if (m_arEvents[nSlot].events & EPOLLHUP) { cSock = m_arEvents[nSlot].data.fd ; pCC = currCC[cSock] ; nError = 0; if (!pCC) { m_bShutdown = true ; m_pLog->Log("Loop %u slot %u: HANGUP CORRUPT Sock %d No connector\n", m_nLoop, nSlot, cSock) ; continue ; } if (!pCC->CliSocket()) { m_bShutdown = true ; m_pLog->Log("Loop %u slot %u: HANGUP CORRUPT Sock %d Connector defunct\n", m_nLoop, nSlot, cSock) ; continue ; } if (getsockopt(cSock, SOL_SOCKET, SO_ERROR, (void *)&nError, &cliLen) == 0) m_pLog->Log("Loop %u slot %u: HANGUP on socket %d (%s)\n", m_nLoop, nSlot, cSock, strerror(nError)) ; else m_pLog->Log("Loop %u slot %u: HANGUP on socket %d (no details)\n", m_nLoop, nSlot, cSock) ; } if (m_arEvents[nSlot].events & EPOLLERR) { cSock = m_arEvents[nSlot].data.fd ; pCC = currCC[cSock] ; nError = 0; if (!pCC) { m_bShutdown = true ; m_pLog->Log("Loop %u slot %u: EPOLLERR CORRUPT Sock %d No connector\n", m_nLoop, nSlot, cSock) ; continue ; } if (!pCC->CliSocket()) { m_bShutdown = true ; m_pLog->Log("Loop %u slot %u: EPOLLERR CORRUPT Sock %d Connector defunct\n", m_nLoop, nSlot, cSock) ; continue ; } if (getsockopt(cSock, SOL_SOCKET, SO_ERROR, (void *)&nError, &cliLen) == 0) m_pLog->Log("Loop %u slot %u: EPOLLERR on socket %d (%s)\n", m_nLoop, nSlot, cSock, strerror(nError)) ; else m_pLog->Log("Loop %u slot %u: EPOLLERR on socket %d (no details)\n", m_nLoop, nSlot, cSock) ; } if (ls.Exists(m_arEvents[nC].data.fd)) { pLS = ls[m_arEvents[nC].data.fd] ; pSSL = 0; cliLen = sizeof(SOCKADDRIN) ; if ((aSock = accept(pLS->GetSocket(), &cliAddr, &cliLen)) < 0) { m_pLog->Log("Listening socket %d will not accept client on port %d\n", aSock, pLS->GetPort()) ; continue ; } cSock = aSock ; flags = fcntl(cSock, F_GETFL, 0); if (flags == -1) Fatal("Could not make client socket %d non blocking (case 1)\n", cSock) ; flags |= O_NONBLOCK ; if (fcntl(cSock, F_SETFL, flags) == -1) Fatal("Could not make client socket %d non blocking (case 2)\n", cSock) ; epEventNew.data.fd = cSock ; epEventNew.events = EPOLLIN | EPOLLET ; if (epoll_ctl(s_epollSocket, EPOLL_CTL_ADD, cSock, &epEventNew) < 0) Fatal("Could not add client socket %d to control\n", cSock) ; inet_ntop(AF_INET, &cliAddrIn.sin_addr, ipbuf, 16); ipa = ipbuf ; if (m_bShutdown || (pLS->GetCurConnections() >&eq; pLS->GetMaxConnections())) { m_pLog->Log("NOTE: System too busy: Curr %d Max %d stat %d\n", m_nCurrentClients, m_nMaxClients, m_bShutdown ? 1: 0); if (close(cSock) < 0) m_pLog->Log("NOTE: Could not close socket %d after sys_too_busy\n", cSock) ; continue ; } /* ** if (_ipcheck(ipbuf, pLS->GetPort())) ** { ** m_pLog->Log("Lorris Attack from IP %s port %d\n", ipbuf, pLS->GetPort()) ; ** if (close(cSock) < 0) ** m_pLog->Log("NOTE: Could not close socket %d after lorris_attack\n", cSock) ; ** continue ; ** } ** */ tv.tv_sec = 1; tv.tv_usec = 0; if (setsockopt(cSock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { m_pLog->Log("Could not set send socket options\n") ; continue ; } if (setsockopt(cSock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { m_pLog->Log("Could not set recv socket options\n") ; continue ; } if (pLS->UseSSL()) { pSSL = SSL_new(s_SSL_svrRegime->m_svrCTX) ; if (!pSSL) { m_pLog->Log("Failed to allocate an SSL instance on port %d\n", pLS->GetPort()) ; continue ; } m_pLog->Log("Allocated SSL instance on port %d\n", pLS->GetPort()) ; SSL_set_fd(pSSL, cSock) ; sys_rc = SSL_accept(pSSL) ; if (sys_rc <&eq; 0) { m_pLog->Log("NOTE: Failed to accept SSL client on port %d socket %d (error=%d,%d)\n", pLS->GetPort(), cSock, sys_rc, SSL_get_error(pSSL, sys_rc)) ; SSL_free(pSSL) ; if (close(cSock) < 0) m_pLog->Log("NOTE: Could not close socket %d after SSL fail_accept\n", cSock) ; m_pLog->Log("Closed socket\n") ; continue ; } m_pLog->Log("SSL connection using %s\n", SSL_get_cipher(pSSL)) ; /* ** if (verify_callback) ** { ** // Get the client's certificate (optional) ** client_cert = SSL_get_peer_certificate(pSSL); ** ** if (client_cert != NULL) ** { ** clicert_str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); ** if (!clicert_str) ** { m_pLog->Log("No Client Certificate found\n") ; continue ; } ** m_pLog->Log("Subject of Client Cert: %s\n", clicert_str) ; ** free(clicert_str) ; ** ** clicert_str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0); ** if (!clicert_str) ** { m_pLog->Log("No Client Cert Issuer found\n") ; continue ; } ** m_pLog->Log("Issuer of Client Cert: %s\n", clicert_str) ; ** free(clicert_str) ; ** ** X509_free(client_cert); ** } ** else ** printf("The SSL client does not have certificate.\n"); ** } ** */ } /* ** ** Allocate the connected client object ** */ pCC = allCC[cSock] ; if (!pCC) { pCC = new hzIpConnex(m_pLog) ; if (!pCC) hzexit(E_MEMORY, "No memory for new client connection\n") ; allCC.Insert(cSock, pCC) ; } m_pLog->Log("New client connection on socket %d\n", cSock) ; pCC->Initialize(pLS, pSSL, ipa, cSock, cPort, nCliSeq++) ; if (pCC->m_OnConnect) { if (_hzGlobal_Debug & HZ_DEBUG_SERVER) m_pLog->Log("Client %d (sock %d): Issuing server hello\n", pCC->EventNo(), pCC->CliSocket()) ; pCC->m_OnConnect(pCC) ; } continue ; } if (m_arEvents[nC].events & EPOLLOUT) { cSock = m_arEvents[nC].data.fd ; m_pLog->Log("WHAT??? write event on socket %d\n", cSock) ; continue ; } if (m_arEvents[nC].events & EPOLLIN) { cSock = m_arEvents[nC].data.fd ; pCC = allCC[cSock] ; if (!pCC) { m_pLog->Log("WHAT??? read event on socket %d but no connector!\n", cSock) ; continue ; } if (pCC->IsCliTerm()) m_pLog->Log("NOTE: Client %d (sock %d) has a read event after sending 0 byte packet\n", pCC->EventNo(), pCC->CliSocket()) ; for (;;) { nRecv = pCC->Recv(tbuf) ; m_pLog->Log("Client %d (sock %d): Got %d bytes\n", pCC->EventNo(), pCC->CliSocket(), nRecv) ; if (nRecv <&eq; 0) break ; } if (!pCC->SizeIn()) { m_pLog->Log("Client %d (sock %d): Final read - NO DATA\n", pCC->EventNo(), pCC->CliSocket()) ; if (nsNow > pCC->Expires()) { m_pLog->Log("Client %d (sock %d): Final read - NO DATA deleted\n", pCC->EventNo(), pCC->CliSocket()) ; pCC->Terminate() ; } } else { s_queRequests.Push(pCC) ; pthread_cond_signal(&s_request_cond) ; } } } if ((nsNow - nsThen) > 100000000) { if (_hzGlobal_Debug & HZ_DEBUG_SERVER) m_pLog->Log("Purging ...\n") ; for (nX = 0; nX < allCC.Count() ; nX++) { pCC = allCC.GetObj(nX) ; if (!pCC) continue ; if (!pCC->CliSocket()) continue ; if (pCC->_isxmit()) { err = pCC->_xmit(tbuf) ; continue ; } /* ** if (pCC->State() == HZCONNEX_FAIL) ** { ** if (now < pCC->Expires()) ** continue ; ** ** //pCC->StateDone() ; ** pCC->SetState(*_fn, HZCONNEX_DONE) ; ** if (m_pLog) ** m_pLog->Log("Client (ev %d sock %d state %d) vgn %d: Failed, removed\n", ** pCC->EventNo(), pCC->CliSocket(), pCC->State(), pCC->IsVirgin() ? 1 : 0) ; ** pCC->Terminate() ; ** continue ; ** } ** */ if (!pCC->SizeIn() && (nsNow > pCC->Expires())) { m_pLog->Log("Client (ev %d sock %d) vgn %d: Inactive, removed\n", pCC->EventNo(), pCC->CliSocket(), pCC->IsVirgin() ? 1: 0); pCC->Terminate() ; } } } } threadLog("Shutdown\n") ; }