| 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") ;
}