** Check for hangups and other connection errors
| Return Type | Function name | Arguments |
|---|---|---|
| void | hzIpServer::Serve | (void) |
Declared in file: hzIpServer.h
Defined in file : hzIpServer.cpp
Function Logic:
Function body:
void hzIpServer::Serve (void)
{
_hzfunc("hzIpServer::Serve") ;
hzList <hzIpListen*>::Iter I ;
struct epoll_event epEventNew ;
hzPacket tbuf ;
SOCKADDRIN cliAddrIn ;
socklen_t cliLen ;
hzIpListen* pLS ;
hzIpConnex* pCC ;
SSL* pUDP_SSL ;
hzProcInfo proc_data ;
hzIpinfo* ipi ;
hzChain errMsg ;
hzXDate now ;
pthread_attr_t tattr ;
timeval tv ;
hzIpaddr ipa ;
uint32_t nCliSeq ;
uint32_t nSlot ;
uint32_t nEpollEvents ;
uint32_t nError ;
uint32_t cSock ;
uint32_t cPort ;
uint32_t nBannedAttempts ;
int32_t flags ;
int32_t nRecv ;
int32_t nRecvTotal ;
int32_t sys_rc ;
int32_t sys_err ;
int32_t xmitState ;
bool bCloseSSL ;
hzTcpCode trc ;
char ipbuf[44];
pthread_attr_init(&tattr) ;
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) ;
for (nSlot = 0; nSlot < 1024;nSlot++)
currCC[nSlot] = 0;
cliLen = sizeof(cliAddrIn) ;
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()) ;
m_mapLS.Insert(pLS->GetSocket(), pLS) ;
}
/*
** ** Main loop - waiting for events
** */
m_nLoop = nCliSeq = nBannedAttempts = 0;
for (;;)
{
if (m_bShutdown)
{
for (nSlot = 0; nSlot < 1024;nSlot++)
{
if (currCC[nSlot])
break ;
}
if (nSlot == 1024)
break ;
}
for (nSlot = 0; nSlot < ConnInError.Count() ; nSlot++)
{
pCC = ConnInError.GetObj(nSlot) ;
}
nEpollEvents = epoll_wait(s_epollSocket, m_arEvents, MAXEVENTS, 60000);
m_nLoop++ ;
if (!nEpollEvents)
m_pLog->Log("Loop %u No action\n", m_nLoop) ;
for (nSlot = 0; nSlot < nEpollEvents ; nSlot++)
{
/*
** ** Check for hangups and other connection errors
** */
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) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
continue ;
}
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) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
continue ;
}
/*
** ** Events on listening sockets
** */
if (m_mapLS.Exists(m_arEvents[nSlot].data.fd))
{
pLS = m_mapLS[m_arEvents[nSlot].data.fd] ;
pUDP_SSL = 0;
if (pLS->UseUDP())
{
cSock = pLS->GetSocket() ;
flags = fcntl(pLS->GetSocket(), F_GETFL, 0);
if (flags == -1)
{
m_pLog->Log("UDP: Loop %u: NOTE: Could not make client socket %d non blocking (case 1)\n", m_nLoop, pLS->GetSocket()) ;
if (close(pLS->GetSocket()) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after non_block_fail(1) errno=%d\n", m_nLoop, pLS->GetSocket(), errno) ;
continue ;
}
flags |= O_NONBLOCK ;
if (fcntl(pLS->GetSocket(), F_SETFL, flags) == -1)
{
m_pLog->Log("UDP: Loop %u: NOTE: Could not make client socket %d non blocking (case 2)\n", m_nLoop, pLS->GetSocket()) ;
if (close(pLS->GetSocket()) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after non_block_fail(2) errno=%d\n", m_nLoop, pLS->GetSocket(), errno) ;
continue ;
}
if ((nRecv = recvfrom(pLS->GetSocket(), tbuf.m_data, HZ_MAXPACKET, 0,(SOCKADDR*) &cliAddrIn, &cliLen)) < 0)
{
m_pLog->Log("UDP: Loop %u: NOTE: Could not read from UDP client\n", m_nLoop) ;
continue ;
}
ipa = (uint32_t) cliAddrIn.sin_addr.s_addr ;
cPort = ntohs(cliAddrIn.sin_port) ;
tbuf.m_data[nRecv] = 0;
pCC = udpClients[ipa] ;
if (!pCC)
{
pCC = new hzIpConnex(m_pLog) ;
udpClients.Insert(ipa, pCC) ;
pCC->Initialize(pLS, pUDP_SSL, ipa, cSock, cPort, nCliSeq++) ;
if (pCC->m_OnConnect)
pCC->m_OnConnect(pCC) ;
}
m_pLog->Out("Received UDP message %s from port %d internet address %s\n", tbuf.m_data, cPort, *ipa) ;
if (pCC->MsgReady())
trc = pCC->m_OnIngress(pCC->InputZone(), pCC) ;
else
trc = TCP_INCOMPLETE ;
switch (trc)
{
case TCP_TERMINATE:
if (pCC->_isxmit())
{
xmitState = pCC->_xmit(tbuf) ;
if (xmitState < 0)
{
m_pLog->Log("UDP: Loop %u slot %u: TCP_TERMINATE: Write error - Sock %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
udpClients.Delete(ipa) ;
delete pCC ;
break ;
}
if (xmitState > 0)
{
m_pLog->Log("UDP: Loop %u slot %u: TCP_TERMINATE: Write delay - Sock %d /%d, looking for write event\n",
m_nLoop, nSlot, cSock, pCC->CliPort()) ;
break ;
}
}
m_pLog->Log("UDP: Loop %u slot %u: TCP_TERMINATE: Normal termination, sock %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
udpClients.Delete(ipa) ;
delete pCC ;
break ;
case TCP_KEEPALIVE:
m_pLog->Log("UDP: Client %d SERVER - data processed, awaiting further messages\n", pCC->EventNo()) ;
pCC->Oxygen() ;
if (pCC->_isxmit())
{
xmitState = pCC->_xmit(tbuf) ;
if (xmitState < 0)
{
m_pLog->Log("UDP: Loop %u slot %u: TCP_KEEPALIVE: Write error, sock %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
udpClients.Delete(ipa) ;
delete pCC ;
break ;
}
if (xmitState > 0)
{
m_pLog->Log("UDP: Loop %u slot %u: TCP_KEEPALIVE: Write delay - Sock %d/%d retained\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
break ;
}
m_pLog->Log("UDP: Loop %u slot %u: TCP_KEEPALIVE: Write OK, sock %d/%d retained\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
}
if (pCC->IsCliTerm())
{
m_pLog->Log("UDP: Loop %u loop %u: TCP_KEEPALIVE: Client done so sock %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
udpClients.Delete(ipa) ;
delete pCC ;
break ;
}
break ;
case TCP_INCOMPLETE:
m_pLog->Log("UDP: Client %d SERVER - data incomplete\n", pCC->EventNo()) ;
pCC->Oxygen() ;
break ;
case TCP_INVALID:
if (m_pLog)
m_pLog->Log("UDP: Loop %u: Sock %d/%d INVALID TCP code\n", m_nLoop, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
udpClients.Delete(ipa) ;
delete pCC ;
break ;
}
continue ;
}
/*
** ** Handle new TCP client connections
** */
cSock = accept(pLS->GetSocket(), (SOCKADDR*) &cliAddrIn, &cliLen) ;
if (cSock < 0)
{
m_pLog->Log("Loop %u: NOTE: Listening socket %d ignored client on port %d\n", m_nLoop, pLS->GetSocket(), pLS->GetPort()) ;
if (errno && errno != EAGAIN && errno != EWOULDBLOCK)
{
m_bShutdown = true ;
m_pLog->Log("Loop %u: SHUTDOWN: Listening socket %d failure: Port %d (errno=%d)\n", m_nLoop, pLS->GetSocket(), pLS->GetPort(), errno) ;
}
continue ;
}
inet_ntop(AF_INET, &cliAddrIn.sin_addr, ipbuf, 16);
ipa = ipbuf ;
cPort = ntohs(cliAddrIn.sin_port) ;
if (_hzGlobal_StatusIP.Exists(ipa))
{
ipi = &(_hzGlobal_StatusIP[ipa]) ;
if (!(ipi->m_bInfo & HZ_IPSTATUS_WHITE) || ipi->m_tWhite < time(0))
{
if (!(ipi->m_nSince%100))
m_pLog->Log("BLOCKED IP %s reaches %u attempts\n", *ipa, ipi->m_nSince) ;
if (close(cSock) < 0)
m_pLog->Log("ERROR: Could not close socket %d after blocked IP address detected. errno=%d\n", cSock, errno) ;
ipi->m_nSince++ ;
ipi->m_nTotal++ ;
nBannedAttempts++ ;
if (!(nBannedAttempts%10000))
m_pLog->Log("BLOCKED IP TOTAL reaches %u attempts\n", nBannedAttempts) ;
continue ;
}
}
if (_hzGlobal_Debug & HZ_DEBUG_SERVER)
m_pLog->Log("Loop %u: Accepted connection (1): socket %d/%d host %s port %d\n", m_nLoop, cSock, cPort, ipbuf, pLS->GetPort()) ;
/*
** ** Allocate the connected client object
** */
pCC = currCC[cSock] ;
if (pCC)
{
m_pLog->Log("Loop %u slot %u: CORRUPT: Existing client connection handler on sock %d/%d.\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
if (close(cSock) < 0)
m_pLog->Log("NOTE: Could not close socket %d after memory allocation failure. errno=%d\n", cSock, errno) ;
m_bShutdown = true ;
continue ;
}
pCC = new hzIpConnex(m_pLog) ;
if (!pCC)
{
m_pLog->Log("ERROR: No memory for client %s on socket %d. Closing conection\n", ipbuf, cSock) ;
if (close(cSock) < 0)
m_pLog->Log("NOTE: Could not close socket %d after memory allocation failure. errno=%d\n", cSock, errno) ;
m_bShutdown = true ;
continue ;
}
if (_nonblock(cSock) != E_OK)
continue ;
if (pLS->UseSSL())
{
tv.tv_sec = 0;
tv.tv_usec = 100000;
if (setsockopt(cSock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
{
m_pLog->Log("Loop %u: NOTE: Could not set send socket options\n", m_nLoop) ;
if (close(cSock) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after setop_send errno=%d\n", m_nLoop, cSock, errno) ;
continue ;
}
if (setsockopt(cSock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
{
m_pLog->Log("Loop %u: NOTE: Could not set recv socket options\n", m_nLoop) ;
if (close(cSock) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after setop_recv errno=%d\n", cSock, errno) ;
continue ;
}
m_pLog->Log("Loop %u: NOTE: SSL instance. Client %s:%d\n", m_nLoop, ipbuf, pLS->GetPort()) ;
pCC->m_pSSL = SSL_new(s_SSL_svrRegime->m_svrCTX) ;
if (!pCC->m_pSSL)
{
m_pLog->Log("Loop %u: NOTE: Failed to allocate an SSL instance on port %d\n", m_nLoop, pLS->GetPort()) ;
if (close(cSock) < 0)
{
m_pLog->Log("NOTE: Could not close socket %d after memory allocation failure. errno=%d\n", cSock, errno) ;
m_bShutdown = true ;
}
continue ;
}
m_pLog->Log("Loop %u: Allocated SSL instance on port %d\n", m_nLoop, pLS->GetPort()) ;
SSL_set_accept_state(pCC->m_pSSL) ;
sys_rc = SSL_set_fd(pCC->m_pSSL, cSock) ;
errMsg.Clear() ;
errMsg.Printf("Loop %u: SSL_set_fd %d - ", m_nLoop, sys_rc) ;
bCloseSSL = false ;
sys_rc = SSL_accept(pCC->m_pSSL) ;
if (sys_rc >&eq; 1)
{
pCC->m_bAcceptSSL = false ;
errMsg << "SSL_accept OK\n" ;
}
else
{
pCC->m_bAcceptSSL = true ;
sys_err = SSL_get_error(pCC->m_pSSL, sys_rc) ;
errMsg.Printf("Failed to accept SSL client port %d sock %d ret %d err=%d ", pLS->GetPort(), cSock, sys_rc, sys_err) ;
switch (sys_err)
{
case SSL_ERROR_ZERO_RETURN: errMsg << "SSL_ERROR_ZERO_RETURN\n" ; bCloseSSL = true ; break ;
case SSL_ERROR_WANT_READ: errMsg << "SSL_ERROR_WANT_READ\n" ; break ;
case SSL_ERROR_WANT_WRITE: errMsg << "SSL_ERROR_WANT_WRITE\n" ; break ;
case SSL_ERROR_WANT_CONNECT: errMsg << "SSL_ERROR_WANT_CONNECT\n" ; break ;
case SSL_ERROR_WANT_ACCEPT: errMsg << "SSL_ERROR_WANT_ACCEPT\n" ; break ;
case SSL_ERROR_WANT_X509_LOOKUP: errMsg << "SSL_ERROR_WANT_ACCEPT\n" ; break ;
case SSL_ERROR_WANT_ASYNC: errMsg << "SSL_ERROR_WANT_ASYNC\n" ; break ;
case SSL_ERROR_WANT_ASYNC_JOB: errMsg << "SSL_ERROR_WANT_ASYNC_JOB\n" ; break ;
case SSL_ERROR_WANT_CLIENT_HELLO_CB: errMsg << "SSL_ERROR_WANT_CLIENT_HELLO_CB\n" ; break ;
case SSL_ERROR_SYSCALL: errMsg << "SSL_ERROR_SYSCALL\n" ; bCloseSSL = true ; break ;
case SSL_ERROR_SSL: errMsg << "SSL_ERROR_SSL\n" ; bCloseSSL = true ; break ;
}
}
m_pLog->Log(errMsg) ;
if (bCloseSSL)
{
SSL_free(pCC->m_pSSL) ;
if (close(cSock) < 0)
{
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after SSL no_alloc errno=%d\n", m_nLoop, cSock, errno) ;
m_bShutdown = true ;
}
continue ;
}
}
if (m_bShutdown || pLS->GetCurConnections() >&eq; pLS->GetMaxConnections())
{
m_pLog->Log("Loop %u: NOTE: System too busy: Curr %d Max %d stat %d\n", m_nLoop, pLS->GetCurConnections(), m_nMaxClients, m_bShutdown ? 1: 0);
if (close(cSock) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after sys_too_busy errno=%d\n", m_nLoop, cSock, errno) ;
continue ;
}
/*
** if (_ipcheck(ipbuf, pLS->GetPort()))
** {
** m_pLog->Log("Loop %u: NOTE: Lorris Attack from IP %s port %d\n", ipbuf, pLS->GetPort()) ;
** if (close(cSock) < 0)
** m_pLog->Log("Loop %u: NOTE: Could not close socket %d after lorris_attack errno=%d\n", m_nLoop, cSock, errno) ;
** continue ;
** }
** */
tv.tv_sec = 20;
tv.tv_usec = 0;
if (setsockopt(cSock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
{
m_pLog->Log("Loop %u: NOTE: Could not set send socket options\n", m_nLoop) ;
if (close(cSock) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after setop_send errno=%d\n", m_nLoop, cSock, errno) ;
continue ;
}
if (setsockopt(cSock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
{
m_pLog->Log("Loop %u: NOTE: Could not set recv socket options\n", m_nLoop) ;
if (close(cSock) < 0)
m_pLog->Log("Loop %u: NOTE: Could not close socket %d after setop_recv errno=%d\n", cSock, errno) ;
continue ;
}
epEventNew.data.fd = cSock ;
epEventNew.events = EPOLLIN ;
if (epoll_ctl(s_epollSocket, EPOLL_CTL_ADD, cSock, &epEventNew) < 0)
{
m_pLog->Log("Loop %u slot %u: EPOLL ERROR: Could not add client connection handler on sock %d/%d. Error=%s\n",
m_nLoop, nSlot, cSock, pCC->CliPort(), strerror(errno)) ;
if (close(cSock) < 0)
m_pLog->Log("NOTE: Could not close socket %d after memory allocation failure. errno=%d\n", cSock, errno) ;
m_bShutdown = true ;
delete pCC ;
continue ;
}
currCC[cSock] = pCC ;
pCC->Initialize(pLS, pCC->m_pSSL, ipa, cSock, cPort, nCliSeq++) ;
if (pCC->m_OnConnect)
pCC->m_OnConnect(pCC) ;
now.SysDateTime() ;
m_pLog->Log("Loop %u slot %u: NEW Connection on socket %d/%d from %s:%u\n", m_nLoop, nSlot, cSock, pCC->CliPort(), ipbuf, pLS->GetPort()) ;
continue ;
}
/*
** ** WRITE Events
** */
if (m_arEvents[nSlot].events & EPOLLOUT)
{
cSock = m_arEvents[nSlot].data.fd ;
pCC = currCC[cSock] ;
if (!pCC)
{
m_pLog->Log("Loop %u slot %u: CORRUPT: Write event on socket %d/%d but no connector!\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
m_bShutdown = true ;
continue ;
}
if (cSock != pCC->CliSocket())
{
m_pLog->Log("Loop %u slot %u: CORRUPT: Write event on sock %d/%d but attached client object has socket of %d\n",
m_nLoop, nSlot, cSock, pCC->CliPort(), pCC->CliSocket()) ;
m_bShutdown = true ;
continue ;
}
if (pCC->IsCliBad())
{
m_pLog->Log("Loop %u slot %u: BAD Client, connection on socket %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
continue ;
}
if (pCC->m_bAcceptSSL)
{
sys_rc = SSL_accept(pCC->m_pSSL) ;
if (sys_rc > 0)
{
pCC->m_bAcceptSSL = false ;
m_pLog->Log("Subsequent SSL_accept OK %d\n", sys_rc) ;
}
else
{
sys_err = SSL_get_error(pCC->m_pSSL, sys_rc) ;
m_pLog->Log("Loop %u: NOTE: Subsequent Failed to accept SSL client port %d sock %d ret %d err=%d\n", m_nLoop, pLS->GetPort(), cSock, sys_rc, sys_err) ;
switch (sys_err)
{
case SSL_ERROR_ZERO_RETURN: bCloseSSL = true ; m_pLog->Log("SSL_ERROR_ZERO_RETURN\n") ; break ;
case SSL_ERROR_WANT_READ: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_READ\n") ; break ;
case SSL_ERROR_WANT_WRITE: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_WRITE\n") ; break ;
case SSL_ERROR_WANT_CONNECT: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_CONNECT\n") ; break ;
case SSL_ERROR_WANT_ACCEPT: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ACCEPT\n") ; break ;
case SSL_ERROR_WANT_X509_LOOKUP: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ACCEPT\n") ; break ;
case SSL_ERROR_WANT_ASYNC: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ASYNC\n") ; break ;
case SSL_ERROR_WANT_ASYNC_JOB: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ASYNC_JOB\n") ; break ;
case SSL_ERROR_WANT_CLIENT_HELLO_CB: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_CLIENT_HELLO_CB\n") ; break ;
case SSL_ERROR_SYSCALL: bCloseSSL = true ; m_pLog->Log("SSL_ERROR_SYSCALL\n") ; break ;
case SSL_ERROR_SSL: bCloseSSL = true ; m_pLog->Log("SSL_ERROR_SSL\n") ; break ;
}
if (bCloseSSL)
{
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
}
continue ;
}
}
if (!pCC->_isxmit() && _hzGlobal_Debug & HZ_DEBUG_SERVER)
m_pLog->Log("Loop %u slot %u: Write event with nothing socket %d/%d\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
if (pCC->_isxmit())
{
xmitState = pCC->_xmit(tbuf) ;
if (xmitState < 0)
{
m_pLog->Log("Loop %u slot %u: EPOLLOUT Write error, connection on socket %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
continue ;
}
}
}
/*
** ** READ Events
** */
if (m_arEvents[nSlot].events & EPOLLIN)
{
cSock = m_arEvents[nSlot].data.fd ;
pCC = currCC[cSock] ;
if (!pCC)
{
m_pLog->Log("Loop %u: CORRUPT: Read event on socket %d/%d but no connector!\n", m_nLoop, cSock, pCC->CliPort()) ;
m_bShutdown = true ;
continue ;
}
if (cSock != pCC->CliSocket())
{
m_pLog->Log("Loop %u slot %u: CORRUPT: Read event on sock %d/%d but attached client object has socket of %d\n",
m_nLoop, nSlot, cSock, pCC->CliPort(), pCC->CliSocket()) ;
m_bShutdown = true ;
continue ;
}
if (pCC->m_bAcceptSSL)
{
bCloseSSL = false ;
sys_rc = SSL_accept(pCC->m_pSSL) ;
if (sys_rc > 0)
{
m_pLog->Log("Subsequent W SSL_accept OK %d\n", sys_rc) ;
}
else
{
sys_err = SSL_get_error(pCC->m_pSSL, sys_rc) ;
m_pLog->Log("Loop %u: NOTE: Subsequent W Failed to accept SSL client port %d sock %d ret %d err=%d\n", m_nLoop, pLS->GetPort(), cSock, sys_rc, sys_err) ;
switch (sys_err)
{
case SSL_ERROR_ZERO_RETURN: bCloseSSL = true ; m_pLog->Log("SSL_ERROR_ZERO_RETURN\n") ; break ;
case SSL_ERROR_WANT_READ: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_READ\n") ; break ;
case SSL_ERROR_WANT_WRITE: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_WRITE\n") ; break ;
case SSL_ERROR_WANT_CONNECT: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_CONNECT\n") ; break ;
case SSL_ERROR_WANT_ACCEPT: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ACCEPT\n") ; break ;
case SSL_ERROR_WANT_X509_LOOKUP: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ACCEPT\n") ; break ;
case SSL_ERROR_WANT_ASYNC: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ASYNC\n") ; break ;
case SSL_ERROR_WANT_ASYNC_JOB: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_ASYNC_JOB\n") ; break ;
case SSL_ERROR_WANT_CLIENT_HELLO_CB: bCloseSSL = false ; m_pLog->Log("SSL_ERROR_WANT_CLIENT_HELLO_CB\n") ; break ;
case SSL_ERROR_SYSCALL: bCloseSSL = true ; m_pLog->Log("SSL_ERROR_SYSCALL\n") ; break ;
case SSL_ERROR_SSL: bCloseSSL = true ; m_pLog->Log("SSL_ERROR_SSL\n") ; break ;
}
if (bCloseSSL)
{
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
}
continue ;
}
}
for (nRecvTotal = 0;; nRecvTotal += nRecv)
{
nRecv = pCC->Recv(tbuf) ;
if (nRecv <&eq; 0)
break ;
}
if (pCC->m_bAcceptSSL)
{
pCC->m_bAcceptSSL = false ;
if (!nRecvTotal)
continue ;
}
if (_hzGlobal_Debug & HZ_DEBUG_SERVER)
{
if (!pCC->IsCliTerm())
m_pLog->Log("Loop %u slot %u: Client LIVE sock %d/%d. Recv %d Have %d\n", m_nLoop, nSlot, cSock, pCC->CliPort(), nRecvTotal, pCC->SizeIn()) ;
else
m_pLog->Log("Loop %u slot %u: Client DONE sock %d/%d. Revc %d Have %d\n", m_nLoop, nSlot, cSock, pCC->CliPort(), nRecvTotal, pCC->SizeIn()) ;
}
if (!nRecvTotal)
{
m_pLog->Log("Loop %u slot %u: Read event with zero data on socket %d - disconnecting\n", m_nLoop, nSlot, cSock) ;
if (!pCC->_isxmit())
{
m_pLog->Log("Loop %u slot %u: Terminating unused connection on socket %d\n", m_nLoop, nSlot, cSock) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
}
}
else
{
if (pCC->m_pProxy)
{
threadLog("Sending back response from proxy\n") ;
pCC->m_pProxy->SendData(pCC->InputZone()) ;
pCC->InputZone().Clear() ;
continue ;
}
if (pCC->MsgReady())
trc = pCC->m_OnIngress(pCC->InputZone(), pCC) ;
else
{
m_pLog->Log("Loop %u slot %u: NOTE: Client message not yet complete on socket %d/%d\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
trc = TCP_INCOMPLETE ;
}
switch (trc)
{
case TCP_TERMINATE:
if (pCC->_isxmit())
{
xmitState = pCC->_xmit(tbuf) ;
if (xmitState < 0)
{
m_pLog->Log("Loop %u slot %u: TCP_TERMINATE: Write error - Sock %d/%d doomed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
break ;
}
}
if (!pCC->_isxmit())
{
m_pLog->Log("Loop %u slot %u: TCP_TERMINATE: Normal termination, sock %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
break ;
}
m_pLog->Log("Loop %u slot %u: TCP_TERMINATE: Write delay - Sock %d/%d\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
break ;
case TCP_KEEPALIVE:
if (pCC->_isxmit())
{
xmitState = pCC->_xmit(tbuf) ;
if (xmitState < 0)
{
m_pLog->Log("Loop %u slot %u: TCP_KEEPALIVE: Write error, sock %d/%d doomed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
break ;
}
if (xmitState > 0)
{
m_pLog->Log("Loop %u slot %u: TCP_KEEPALIVE: Write delay - Sock %d/%d\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
}
}
if (pCC->IsCliTerm())
{
m_pLog->Log("Loop %u slot %u: TCP_KEEPALIVE: Client terminated so sock %d/%d to be removed\n", m_nLoop, nSlot, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
break ;
}
pCC->Oxygen() ;
break ;
case TCP_INCOMPLETE:
pCC->Oxygen() ;
break ;
case TCP_INVALID:
m_pLog->Log("Loop %u: Sock %d/%d INVALID TCP code\n", m_nLoop, cSock, pCC->CliPort()) ;
pCC->Terminate() ;
delete pCC ;
currCC[cSock] = 0;
break ;
}
}
}
}
}
threadLog("SHUTDOWN COMPLETE\n") ;
}