** Check for hangups and other connection errors

Return TypeFunction nameArguments
voidhzIpServer::Serve(void)

Declared in file: hzIpServer.h
Defined in file : hzIpServer.cpp

Function Logic:

0:START 1:pthread_attr_init pthread_attr_setdetachstate nSlot 2:nSlot<1024; 3:currCC 4:cliLen epoll_create1 s_epollSocket 5:s_epollSocket==-1 6:Fatal 7:hzLogger::Log I 8:I.Valid(); 9:hzList::Iter::Element pLS hzIpListen::GetSocket epEventNew epEventNew 10:epoll_ctl(s_epollSocket,EPOLL_CTL_ADD,pLS->GetSocket(),&epEventNew)<0 11:hzIpListen::GetSocket Fatal 12:hzIpListen::GetSocket hzLogger::Log hzIpListen::GetSocket hzMapS::Insert 13:nBannedAttempts nCliSeq m_nLoop 14:; 15:m_bShutdown 16:nSlot<1024; 17:currCC[nSlot] 18:nSlot==1024 19:nSlot 20:hzMapS::GetObj pCC 21:epoll_wait nEpollEvents items 22:!nEpollEvents 23:hzLogger::Log nSlot 24:nSlot 25:m_arEvents[nSlot].events&EPOLLHUP 26:cSock pCC nError 27:!pCC 28:m_bShutdown hzLogger::Log 29:!pCC->CliSocket() 30:m_bShutdown hzLogger::Log 31:getsockopt(cSock,SOL_SOCKET,SO_ERROR,(void*)&nError,&cliLen)==0 32:strerror hzLogger::Log 33:hzLogger::Log 34:hzIpConnex::Terminate pCC currCC 35:m_arEvents[nSlot].events&EPOLLERR 36:cSock pCC nError 37:!pCC 38:m_bShutdown hzLogger::Log 39:!pCC->CliSocket() 40:m_bShutdown hzLogger::Log 41:getsockopt(cSock,SOL_SOCKET,SO_ERROR,(void*)&nError,&cliLen)==0 42:strerror hzLogger::Log 43:hzLogger::Log 44:hzIpConnex::Terminate pCC currCC 45:m_mapLS.Exists(m_arEvents[nSlot].data.fd) 46:pLS pUDP_SSL hzIpListen::UseUDP 47:pLS->UseUDP() 48:hzIpListen::GetSocket cSock hzIpListen::GetSocket fcntl flags 49:flags==-1 50:hzIpListen::GetSocket hzLogger::Log 51:close(pLS->GetSocket())<0 52:hzIpListen::GetSocket hzLogger::Log 53:flags 54:fcntl(pLS->GetSocket(),F_SETFL,flags)==-1 55:hzIpListen::GetSocket hzLogger::Log 56:close(pLS->GetSocket())<0 57:hzIpListen::GetSocket hzLogger::Log 58:(nRecv=recvfrom(pLS->GetSocket(),tbuf.m_data,HZ_MAXPACKET,0,(SOCKADDR*)&cliAddrIn,&cliLen))<0 59:hzLogger::Log 60:ipa ntohs cPort tbuf pCC 61:!pCC 62:pCC hzMapS::Insert hzIpConnex::Initialize 63:pCC->m_OnConnect 64:items 65:hzLogger::Out hzIpConnex::MsgReady 66:pCC->MsgReady() 67:trc 68:trc 69:trc 70:TCP_TERMINATE 71:pCC->_isxmit() 72:hzIpConnex::_xmit xmitState 73:xmitState<0 74:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate hzMapS::Delete pCC 75:xmitState>0 76:hzIpConnex::CliPort hzLogger::Log 77:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate hzMapS::Delete pCC 78:TCP_KEEPALIVE 79:hzIpConnex::EventNo hzLogger::Log hzIpConnex::Oxygen hzIpConnex::_isxmit 80:pCC->_isxmit() 81:hzIpConnex::_xmit xmitState 82:xmitState<0 83:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate hzMapS::Delete pCC 84:xmitState>0 85:hzIpConnex::CliPort hzLogger::Log 86:hzIpConnex::CliPort hzLogger::Log hzIpConnex::IsCliTerm 87:pCC->IsCliTerm() 88:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate hzMapS::Delete pCC 89:TCP_INCOMPLETE 90:hzIpConnex::EventNo hzLogger::Log hzIpConnex::Oxygen 91:TCP_INVALID 92:m_pLog 93:hzIpConnex::CliPort hzLogger::Log 94:hzIpConnex::Terminate hzMapS::Delete pCC 95:hzIpListen::GetSocket accept cSock 96:cSock<0 97:hzIpListen::GetSocket hzIpListen::GetPort hzLogger::Log 98:errno&&errno!=EAGAIN&&errno!=EWOULDBLOCK 99:m_bShutdown hzIpListen::GetSocket hzIpListen::GetPort hzLogger::Log 100:inet_ntop ipa ntohs cPort hzMapS::Exists 101:_hzGlobal_StatusIP.Exists(ipa) 102:ipi 103:!(ipi->m_bInfo&HZ_IPSTATUS_WHITE)||ipi->m_tWhite 104:!(ipi->m_nSince%100) 105:hzLogger::Log 106:close(cSock)<0 107:hzLogger::Log 108:items items items 109:!(nBannedAttempts%10000) 110:hzLogger::Log 111:_hzGlobal_Debug&HZ_DEBUG_SERVER 112:hzIpListen::GetPort hzLogger::Log 113:pCC 114:pCC 115:hzIpConnex::CliPort hzLogger::Log 116:close(cSock)<0 117:hzLogger::Log 118:m_bShutdown 119:pCC 120:!pCC 121:hzLogger::Log 122:close(cSock)<0 123:hzLogger::Log 124:m_bShutdown 125:_nonblock(cSock)!=E_OK 126:pLS->UseSSL() 127:tv tv 128:setsockopt(cSock,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv))<0 129:hzLogger::Log 130:close(cSock)<0 131:hzLogger::Log 132:setsockopt(cSock,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv))<0 133:hzLogger::Log 134:close(cSock)<0 135:hzLogger::Log 136:hzIpListen::GetPort hzLogger::Log SSL_new pCC 137:!pCC->m_pSSL 138:hzIpListen::GetPort hzLogger::Log 139:close(cSock)<0 140:hzLogger::Log m_bShutdown 141:hzIpListen::GetPort hzLogger::Log SSL_set_accept_state SSL_set_fd sys_rc hzChain::Clear hzChain::Printf bCloseSSL SSL_accept sys_rc 142:sys_rc>=1 143:pCC items 144:pCC SSL_get_error sys_err hzIpListen::GetPort hzChain::Printf 145:sys_err 146:SSL_ERROR_ZERO_RETURN 147:items bCloseSSL 148:SSL_ERROR_WANT_READ 149:items 150:SSL_ERROR_WANT_WRITE 151:items 152:SSL_ERROR_WANT_CONNECT 153:items 154:SSL_ERROR_WANT_ACCEPT 155:items 156:SSL_ERROR_WANT_X509_LOOKUP 157:items 158:SSL_ERROR_WANT_ASYNC 159:items 160:SSL_ERROR_WANT_ASYNC_JOB 161:items 162:SSL_ERROR_WANT_CLIENT_HELLO_CB 163:items 164:SSL_ERROR_SYSCALL 165:items bCloseSSL 166:SSL_ERROR_SSL 167:items bCloseSSL 168:hzLogger::Log 169:bCloseSSL 170:SSL_free 171:close(cSock)<0 172:hzLogger::Log m_bShutdown 173:m_bShutdown||pLS->GetCurConnections()>=pLS->GetMaxConnections() 174:hzIpListen::GetCurConnections hzLogger::Log 175:close(cSock)<0 176:hzLogger::Log 177:tv tv 178:setsockopt(cSock,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv))<0 179:hzLogger::Log 180:close(cSock)<0 181:hzLogger::Log 182:setsockopt(cSock,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv))<0 183:hzLogger::Log 184:close(cSock)<0 185:hzLogger::Log 186:epEventNew epEventNew 187:epoll_ctl(s_epollSocket,EPOLL_CTL_ADD,cSock,&epEventNew)<0 188:hzIpConnex::CliPort strerror hzLogger::Log 189:close(cSock)<0 190:hzLogger::Log 191:m_bShutdown pCC 192:currCC hzIpConnex::Initialize 193:pCC->m_OnConnect 194:items 195:hzXDate::SysDateTime hzIpConnex::CliPort hzIpListen::GetPort hzLogger::Log 196:m_arEvents[nSlot].events&EPOLLOUT 197:cSock pCC 198:!pCC 199:hzIpConnex::CliPort hzLogger::Log m_bShutdown 200:cSock!=pCC->CliSocket() 201:hzIpConnex::CliPort hzIpConnex::CliSocket hzLogger::Log m_bShutdown 202:pCC->IsCliBad() 203:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 204:pCC->m_bAcceptSSL 205:SSL_accept sys_rc 206:sys_rc>0 207:pCC hzLogger::Log 208:SSL_get_error sys_err hzIpListen::GetPort hzLogger::Log 209:sys_err 210:SSL_ERROR_ZERO_RETURN 211:bCloseSSL hzLogger::Log 212:SSL_ERROR_WANT_READ 213:bCloseSSL hzLogger::Log 214:SSL_ERROR_WANT_WRITE 215:bCloseSSL hzLogger::Log 216:SSL_ERROR_WANT_CONNECT 217:bCloseSSL hzLogger::Log 218:SSL_ERROR_WANT_ACCEPT 219:bCloseSSL hzLogger::Log 220:SSL_ERROR_WANT_X509_LOOKUP 221:bCloseSSL hzLogger::Log 222:SSL_ERROR_WANT_ASYNC 223:bCloseSSL hzLogger::Log 224:SSL_ERROR_WANT_ASYNC_JOB 225:bCloseSSL hzLogger::Log 226:SSL_ERROR_WANT_CLIENT_HELLO_CB 227:bCloseSSL hzLogger::Log 228:SSL_ERROR_SYSCALL 229:bCloseSSL hzLogger::Log 230:SSL_ERROR_SSL 231:bCloseSSL hzLogger::Log 232:bCloseSSL 233:hzIpConnex::Terminate pCC currCC 234:!pCC->_isxmit()&&_hzGlobal_Debug&HZ_DEBUG_SERVER 235:hzIpConnex::CliPort hzLogger::Log hzIpConnex::_isxmit 236:pCC->_isxmit() 237:hzIpConnex::_xmit xmitState 238:xmitState<0 239:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 240:m_arEvents[nSlot].events&EPOLLIN 241:cSock pCC 242:!pCC 243:hzIpConnex::CliPort hzLogger::Log m_bShutdown 244:cSock!=pCC->CliSocket() 245:hzIpConnex::CliPort hzIpConnex::CliSocket hzLogger::Log m_bShutdown 246:pCC->m_bAcceptSSL 247:bCloseSSL SSL_accept sys_rc 248:sys_rc>0 249:hzLogger::Log 250:SSL_get_error sys_err hzIpListen::GetPort hzLogger::Log 251:sys_err 252:SSL_ERROR_ZERO_RETURN 253:bCloseSSL hzLogger::Log 254:SSL_ERROR_WANT_READ 255:bCloseSSL hzLogger::Log 256:SSL_ERROR_WANT_WRITE 257:bCloseSSL hzLogger::Log 258:SSL_ERROR_WANT_CONNECT 259:bCloseSSL hzLogger::Log 260:SSL_ERROR_WANT_ACCEPT 261:bCloseSSL hzLogger::Log 262:SSL_ERROR_WANT_X509_LOOKUP 263:bCloseSSL hzLogger::Log 264:SSL_ERROR_WANT_ASYNC 265:bCloseSSL hzLogger::Log 266:SSL_ERROR_WANT_ASYNC_JOB 267:bCloseSSL hzLogger::Log 268:SSL_ERROR_WANT_CLIENT_HELLO_CB 269:bCloseSSL hzLogger::Log 270:SSL_ERROR_SYSCALL 271:bCloseSSL hzLogger::Log 272:SSL_ERROR_SSL 273:bCloseSSL hzLogger::Log 274:bCloseSSL 275:hzIpConnex::Terminate pCC currCC 276:; 277:hzIpConnex::Recv nRecv 278:nRecv<=0 279:pCC->m_bAcceptSSL 280:pCC 281:!nRecvTotal 282:_hzGlobal_Debug&HZ_DEBUG_SERVER 283:!pCC->IsCliTerm() 284:hzIpConnex::CliPort hzIpConnex::SizeIn hzLogger::Log 285:hzIpConnex::CliPort hzIpConnex::SizeIn hzLogger::Log 286:!nRecvTotal 287:hzLogger::Log hzIpConnex::_isxmit 288:!pCC->_isxmit() 289:hzLogger::Log hzIpConnex::Terminate pCC currCC 290:pCC->m_pProxy 291:hzIpConnex::InputZone hzIpConnex::SendData hzIpConnex::InputZone hzChain::Clear 292:pCC->MsgReady() 293:trc 294:hzIpConnex::CliPort hzLogger::Log trc 295:trc 296:TCP_TERMINATE 297:pCC->_isxmit() 298:hzIpConnex::_xmit xmitState 299:xmitState<0 300:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 301:!pCC->_isxmit() 302:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 303:hzIpConnex::CliPort hzLogger::Log 304:TCP_KEEPALIVE 305:pCC->_isxmit() 306:hzIpConnex::_xmit xmitState 307:xmitState<0 308:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 309:xmitState>0 310:hzIpConnex::CliPort hzLogger::Log 311:pCC->IsCliTerm() 312:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 313:hzIpConnex::Oxygen 314:TCP_INCOMPLETE 315:hzIpConnex::Oxygen 316:TCP_INVALID 317:hzIpConnex::CliPort hzLogger::Log hzIpConnex::Terminate pCC currCC 318: No text

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