ANSC_STATUS AnscDetoStop ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; if ( !pMyObject->bStarted ) { return ANSC_STATUS_SUCCESS; } else { pMyObject->bStarted = FALSE; } AnscWaitEvent(&pMyObject->RecvEvent, ANSC_DETO_TASK_CLEANUP_TIME); AnscWaitEvent(&pMyObject->SendEvent, ANSC_DETO_TASK_CLEANUP_TIME); pMyObject->Reset((ANSC_HANDLE)pMyObject); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDktoTsaSendTlsMessage ( ANSC_HANDLE hThisObject, ANSC_HANDLE hMessageBdo ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SOCKET_TCP_OBJECT pMyObject = (PANSC_DAEMON_SOCKET_TCP_OBJECT)hThisObject; PANSC_DAEMON_SERVER_TCP_OBJECT pServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer; PANSC_DAEMON_ENGINE_TCP_OBJECT pEngine = (PANSC_DAEMON_ENGINE_TCP_OBJECT)pMyObject->hDaemonEngine; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pServer->hWorker; PANSC_BUFFER_DESCRIPTOR pPayloadBdo = (PANSC_BUFFER_DESCRIPTOR )hMessageBdo; if ( pMyObject->bClosed || pMyObject->bBroken ) { return ANSC_STATUS_UNAPPLICABLE; } returnStatus = pEngine->Send2 ( (ANSC_HANDLE)pEngine, (ANSC_HANDLE)pMyObject, AnscBdoGetBlock (pPayloadBdo), AnscBdoGetBlockSize(pPayloadBdo), (ANSC_HANDLE)NULL ); AnscFreeBdo((ANSC_HANDLE)pPayloadBdo); return returnStatus; }
ANSC_STATUS AnscDstoStopEngines ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SERVER_TCP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_TCP_OBJECT)hThisObject; PANSC_DAEMON_ENGINE_TCP_OBJECT pEngine = NULL; PSINGLE_LINK_ENTRY pSLinkEntry = NULL; AnscAcquireLock(&pMyObject->EngineQueueLock); pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->EngineQueue); while ( pSLinkEntry ) { pEngine = ACCESS_ANSC_DAEMON_ENGINE_TCP_OBJECT(pSLinkEntry); pSLinkEntry = AnscQueueGetNextEntry(pSLinkEntry); pEngine->Stop((ANSC_HANDLE)pEngine); } AnscReleaseLock(&pMyObject->EngineQueueLock); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDetoStart ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; if ( pMyObject->bStarted ) { return ANSC_STATUS_SUCCESS; } else { pMyObject->Reset((ANSC_HANDLE)pMyObject); pMyObject->StartTime = AnscGetTickInSecondsAbs(); pMyObject->bStarted = TRUE; } if ( TRUE ) { AnscResetEvent(&pMyObject->RecvEvent); returnStatus = AnscSpawnTask3 ( (void*)pMyObject->RecvTask, (ANSC_HANDLE)pMyObject, ANSC_DETO_RECV_TASK_NAME, ANSC_TASK_PRIORITY_NORMAL, ANSC_DETO_RECV_TASK_STACK_SIZE ); } if ( pMyObject->ControlFlags & ANSC_DETO_FLAG_ASYNC_SEND ) { AnscResetEvent(&pMyObject->SendEvent); returnStatus = AnscSpawnTask ( (void*)pMyObject->SendTask, (ANSC_HANDLE)pMyObject, ANSC_DETO_SEND_TASK_NAME ); } return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDstoStartEngines ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SERVER_TCP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_TCP_OBJECT)hThisObject; PANSC_DAEMON_ENGINE_TCP_OBJECT pEngine = NULL; ULONG ulFlags = 0; PSINGLE_LINK_ENTRY pSLinkEntry = NULL; AnscAcquireLock(&pMyObject->EngineQueueLock); pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->EngineQueue); while ( pSLinkEntry ) { pEngine = ACCESS_ANSC_DAEMON_ENGINE_TCP_OBJECT(pSLinkEntry); pSLinkEntry = AnscQueueGetNextEntry(pSLinkEntry); ulFlags = pEngine->GetControlFlags((ANSC_HANDLE)pEngine); if ( pMyObject->Mode & ANSC_DSTO_MODE_ASYNC_SEND ) { ulFlags |= ANSC_DETO_FLAG_ASYNC_SEND; } if ( pMyObject->Mode & ANSC_DSTO_MODE_NO_TIMEOUT ) { ulFlags |= ANSC_DETO_FLAG_NO_TIMEOUT; } pEngine->SetControlFlags((ANSC_HANDLE)pEngine, ulFlags); pEngine->Start ((ANSC_HANDLE)pEngine); } AnscReleaseLock(&pMyObject->EngineQueueLock); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDstoPoEngineCloseUp ( ANSC_HANDLE hThisObject, ANSC_HANDLE hForm, ULONG ulIndex ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SERVER_TCP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_TCP_OBJECT)hThisObject; PANSC_DSTO_CLOSE_UP_FORM pCloseUpForm = (PANSC_DSTO_CLOSE_UP_FORM )hForm; PANSC_DAEMON_ENGINE_TCP_OBJECT pEngine = NULL; PSINGLE_LINK_ENTRY pSLinkEntry = NULL; AnscAcquireLock(&pMyObject->EngineQueueLock); pSLinkEntry = AnscQueueSearchEntryByIndex(&pMyObject->EngineQueue, ulIndex); AnscReleaseLock(&pMyObject->EngineQueueLock); if ( !pSLinkEntry ) { return ANSC_STATUS_UNAPPLICABLE; } else { pEngine = ACCESS_ANSC_DAEMON_ENGINE_TCP_OBJECT(pSLinkEntry); } returnStatus = pEngine->CloseUp ( (ANSC_HANDLE)pEngine, (ANSC_HANDLE)pCloseUpForm ); pCloseUpForm->EngineIndex = ulIndex; return returnStatus; }
ANSC_STATUS AnscDetoRemove ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; pMyObject->Stop ((ANSC_HANDLE)pMyObject); pMyObject->Reset((ANSC_HANDLE)pMyObject); AnscFreeEvent(&pMyObject->RecvEvent ); AnscFreeEvent(&pMyObject->SendEvent ); AnscFreeEvent(&pMyObject->NewSocketEvent ); AnscFreeLock (&pMyObject->RecvSocketSetLock); AnscFreeLock (&pMyObject->SendSocketSetLock); AnscFreeLock (&pMyObject->SocketTableLock ); AnscFreeLock (&pMyObject->PacketQueueLock ); AnscCoRemove((ANSC_HANDLE)pMyObject); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDstoWorkerTask ( ANSC_HANDLE hSocket ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SOCKET_TCP_OBJECT pSocket = (PANSC_DAEMON_SOCKET_TCP_OBJECT)hSocket; PANSC_DAEMON_SERVER_TCP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_TCP_OBJECT)pSocket->hDaemonServer; PANSC_DAEMON_ENGINE_TCP_OBJECT pEngine = (PANSC_DAEMON_ENGINE_TCP_OBJECT)pSocket->hDaemonEngine; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pMyObject->hWorker; ULONG ulPacketSize = pSocket->RecvPacketSize; pSocket->RecvPacketSize = 0; pSocket->RecvOffset = 0; returnStatus = pWorker->ProcessAsync ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, pSocket->RecvBuffer, ulPacketSize, (ANSC_HANDLE)NULL ); returnStatus = pEngine->EnableRecv ( (ANSC_HANDLE)pEngine, (ANSC_HANDLE)pSocket, TRUE ); return returnStatus; }
ANSC_STATUS AnscDetoClean ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; PANSC_DAEMON_SERVER_TCP_OBJECT pServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pServer->hWorker; PANSC_DAEMON_SOCKET_TCP_OBJECT pSocket = NULL; PSINGLE_LINK_ENTRY pSLinkEntry = NULL; ULONG ulHashIndex = 0; BOOL bSocketFound = FALSE; ULONG ulCurTime = AnscGetTickInSecondsAbs(); ULONG ulTimeout = ANSC_DETO_SOCKET_TIMEOUT; if ( !pMyObject->bStarted ) { return ANSC_STATUS_SUCCESS; } /* else if ( pMyObject->ControlFlags & ANSC_DETO_FLAG_NO_TIMEOUT ) { return ANSC_STATUS_SUCCESS; } */ if ( pMyObject->CurSocketCount >= pMyObject->MaxSocketCount ) { ulTimeout = ANSC_DETO_SOCKET_TIMEOUT2; } else { ulTimeout = ANSC_DETO_SOCKET_TIMEOUT; } ulHashIndex = 0; bSocketFound = FALSE; while ( ulHashIndex < ANSC_DETO_SOCKET_TABLE_SIZE ) { AnscAcquireLock(&pMyObject->SocketTableLock); bSocketFound = FALSE; pSLinkEntry = AnscSListGetFirstEntry(&pMyObject->SocketTable[ulHashIndex]); while ( pSLinkEntry ) { pSocket = ACCESS_ANSC_DAEMON_SOCKET_TCP_OBJECT(pSLinkEntry); pSLinkEntry = AnscSListGetNextEntry(pSLinkEntry); if ( pSocket->bLocked ) { continue; } else if ( pSocket->bToBeCleaned ) { bSocketFound = TRUE; break; } else if ( pMyObject->ControlFlags & ANSC_DETO_FLAG_NO_TIMEOUT ) { continue; } else { ulCurTime = AnscGetTickInSecondsAbs(); } if ( ((ulCurTime - pSocket->LastRecvAt) >= ulTimeout) && ((ulCurTime - pSocket->LastSendAt) >= ulTimeout) ) { bSocketFound = TRUE; break; } } AnscReleaseLock(&pMyObject->SocketTableLock); if ( bSocketFound ) { if ( !pSocket->bTlsEnabled || (pSocket->bTlsEnabled && pSocket->bTlsConnected) ) { returnStatus = pWorker->Notify ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, ANSC_DSTOWO_EVENT_TIME_OUT, (ANSC_HANDLE)NULL ); } returnStatus = pMyObject->DelSocket ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->TtcCount++; } else { ulHashIndex++; } } return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDstoAsyncJobTask ( ANSC_HANDLE hAsyncJob ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DSTO_ASYNC_JOB pAsyncJob = (PANSC_DSTO_ASYNC_JOB )hAsyncJob; PANSC_DAEMON_SERVER_TCP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_TCP_OBJECT)pAsyncJob->hThisObject; PANSC_DAEMON_ENGINE_TCP_OBJECT pCurEngine = (PANSC_DAEMON_ENGINE_TCP_OBJECT)NULL; PANSC_DAEMON_SOCKET_TCP_OBJECT pSocket = (PANSC_DAEMON_SOCKET_TCP_OBJECT)pAsyncJob->hSocket; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pMyObject->hWorker; ULONG ulRetryCount = 0; switch ( pAsyncJob->JobType ) { case ANSC_DSTO_JOB_TYPE_initTlsConnection : /* * We have to assign an engine object to this new socket object. The assignment is done by * round-robin. However, we need to make sure that the assigned engine object is not over- * loaded. If it is, we repeat the search until finding a happen one. */ ulRetryCount = 0; if ( pSocket->bTlsEnabled ) { returnStatus = pSocket->InitTlsServer((ANSC_HANDLE)pSocket); if ( returnStatus != ANSC_STATUS_SUCCESS ) { /* * I don't understand why this line was commented out before: maybe the * TLS_TSA implementation in AnscDaemonSocketTcp used to clean up socket * object if anything goes wrong? Anyway, it seems a good idea to enable * this line. 07/20/04 - I think the reason is that it's easier to close * socket from the recv() context. */ pSocket->Finish((ANSC_HANDLE)pSocket); pMyObject->TccCount++; break; } } while ( pCurEngine = (PANSC_DAEMON_ENGINE_TCP_OBJECT)pMyObject->AssignEngine ( (ANSC_HANDLE)pMyObject ) ) { returnStatus = pCurEngine->AddSocket ( (ANSC_HANDLE)pCurEngine, (ANSC_HANDLE)pSocket ); if ( returnStatus == ANSC_STATUS_SUCCESS ) { pMyObject->TscCount++; break; } else { ulRetryCount++; if ( ulRetryCount >= pMyObject->EngineCount ) { pSocket->Close ((ANSC_HANDLE)pSocket); pSocket->Return((ANSC_HANDLE)pSocket); pMyObject->TrcCount++; returnStatus = ANSC_STATUS_FAILURE; break; } } } /* * If AddSocket() failed, socket has already been destroyed. In this case, we need * to terminate TLS negotiation task silently. Note that the only scenario where * AddSocket() fails is that the engine is serving a large number of sockets, the * maximum socket number limitation has already been reached. */ if ( returnStatus != ANSC_STATUS_SUCCESS ) { break; } else if ( pSocket->bTlsEnabled ) { returnStatus = pSocket->OpenTlsServer((ANSC_HANDLE)pSocket); if ( returnStatus != ANSC_STATUS_SUCCESS ) { /* * I don't understand why this line was commented out before: maybe the * TLS_TSA implementation in AnscDaemonSocketTcp used to clean up socket * object if anything goes wrong? Anyway, it seems a good idea to enable * this line. 07/20/04 - I think the reason is that it's easier to close * socket from the recv() context. */ pSocket->ToClean((ANSC_HANDLE)pSocket, TRUE, 2); pMyObject->TccCount++; break; } } if ( !pWorker->Accept ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, &pSocket->hClientContext ) ) { pSocket->ToClean((ANSC_HANDLE)pSocket, TRUE, 2); pMyObject->TccCount++; break; } else { returnStatus = pWorker->SetOut ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket ); } /* * Mark the flag that we've completed initializing the TLS connection... */ pSocket->bTlsInitializing = FALSE; break; default : break; } AnscFreeMemory(pAsyncJob); return returnStatus; }
ANSC_STATUS AnscDetoRecvTask ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; PANSC_DAEMON_SERVER_TCP_OBJECT pServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pServer->hWorker; #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) ansc_fd_set* pRecvSet1 = (ansc_fd_set* )pMyObject->RecvSocketSet; xskt_fd_set* pRecvSet2 = (xskt_fd_set* )pMyObject->RecvSocketSet; #endif PANSC_DAEMON_SOCKET_TCP_OBJECT pSocket = NULL; ULONG ulLastCleanAt = AnscGetTickInSecondsAbs(); ANSC_SOCKET s_socket = ANSC_SOCKET_INVALID_SOCKET; int s_result = 0; int s_result_excp = 0; int s_error = 0; int i = 0; #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) ansc_fd_set* read_fd_set1 = NULL; xskt_fd_set* read_fd_set2 = NULL; ansc_fd_set* excp_fd_set1 = NULL; xskt_fd_set* excp_fd_set2 = NULL; ansc_timeval timeval1; xskt_timeval timeval2; #endif AnscTrace("AnscDetoRecvTask is activated ...!\n"); #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) read_fd_set1 = (ansc_fd_set*)AnscAllocateMemory(sizeof(ansc_fd_set)); read_fd_set2 = (xskt_fd_set*)AnscAllocateMemory(sizeof(xskt_fd_set)); excp_fd_set1 = (ansc_fd_set*)AnscAllocateMemory(sizeof(ansc_fd_set)); excp_fd_set2 = (xskt_fd_set*)AnscAllocateMemory(sizeof(xskt_fd_set)); if ( !read_fd_set1 || !read_fd_set2 || !excp_fd_set1 || !excp_fd_set2 ) { goto EXIT1; } #endif /* * As a scalable server implemention, we shall accept as many incoming client connections as * possible and can only be limited by the system resources. Once the listening socket becomes * readable, which means an incoming connection attempt has arrived. We create a new socket * object and associate it with the client. This is a repeated process until the socket owner * closes the socket. */ while ( pMyObject->bStarted ) { ANSC_COMMIT_TASK(); /* * To avoid letting the old half-dead sockets hogging up the system resource, we need to * periodically invoke the cleaning routine. The default interval is 10 seconds, and the * idle timeout value is 90 seconds. */ #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) if ( pMyObject->bCleaningDemanded ) #else if ( FALSE ) /*if ( pMyObject->bCleaningDemanded )*/ #endif { pMyObject->Clean((ANSC_HANDLE)pMyObject); ulLastCleanAt = AnscGetTickInSecondsAbs(); pMyObject->bCleaningDemanded = FALSE; } else if ( (AnscGetTickInSecondsAbs() - ulLastCleanAt) >= ANSC_DETO_CLEAN_TASK_INTERVAL ) { pMyObject->Clean((ANSC_HANDLE)pMyObject); ulLastCleanAt = AnscGetTickInSecondsAbs(); pMyObject->bCleaningDemanded = FALSE; } /* * Since the original bsd compatible socket api doesn't support asynchronous operation, the * nonblocking status polling is the best we can get. As a matter of fact, the current unix * and linux actually still don't support asynchronous notification on any socket operation. */ #if defined(_ANSC_KERNEL) && defined(_ANSC_LINUX) if ( !pMyObject->CurSocketCount) { if ( pServer->Mode & ANSC_DSTO_MODE_EVENT_SYNC ) { AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_DETO_WAIT_EVENT_INTERVAL); AnscResetEvent(&pMyObject->NewSocketEvent); if (!pMyObject->CurSocketCount) { AnscTaskRelinquish(); continue; } } else { AnscSleep(ANSC_DETO_TASK_BREAK_INTERVAL); continue; } } #else if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set2 = *pRecvSet2; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } else { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set1 = *pRecvSet1; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && XSKT_SOCKET_FD_ISNUL(read_fd_set2)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && ANSC_SOCKET_FD_ISNUL(read_fd_set1)) ) { if ( pServer->Mode & ANSC_DSTO_MODE_EVENT_SYNC ) { AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_DETO_WAIT_EVENT_INTERVAL); AnscResetEvent(&pMyObject->NewSocketEvent); if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set2 = *pRecvSet2; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } else { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set1 = *pRecvSet1; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && XSKT_SOCKET_FD_ISNUL(read_fd_set2)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && ANSC_SOCKET_FD_ISNUL(read_fd_set1)) ) { AnscTaskRelinquish(); continue; } } else { AnscSleep(ANSC_DETO_TASK_BREAK_INTERVAL); continue; } } if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { timeval2.tv_sec = (ANSC_DETO_POLL_INTERVAL_MS / 1000); /* number of seconds */ timeval2.tv_usec = (ANSC_DETO_POLL_INTERVAL_MS % 1000) * 1000; /* number of microseconds */ } else { timeval1.tv_sec = (ANSC_DETO_POLL_INTERVAL_MS / 1000); /* number of seconds */ timeval1.tv_usec = (ANSC_DETO_POLL_INTERVAL_MS % 1000) * 1000; /* number of microseconds */ } /* * The _ansc_select() function returns the total number of socket handles that are ready * and contained in the fd_set structures, zero if the time limit expired, or SOCKET_ERROR * if an error occurred. Upon return, the structures are updated to reflect the subset of * these sockets that meet the specified condition. */ if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { s_result = _xskt_select(XSKT_SOCKET_FD_SETSIZE, read_fd_set2, NULL, NULL, &timeval2); } else { s_result = _ansc_select(ANSC_SOCKET_FD_SETSIZE, read_fd_set1, NULL, NULL, &timeval1); } if ( s_result == 0 ) { continue; } else if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_result == XSKT_SOCKET_ERROR)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_result == ANSC_SOCKET_ERROR)) ) { s_error = (pServer->Mode & ANSC_DSTO_MODE_XSOCKET)? _xskt_get_last_error() : _ansc_get_last_error(); /* * Previously we simply reset everything when _ansc_select() fails, which is not a good * solution: we shall notify the worker module and gracefully shutdown the socket(s) * that caused the error. */ /* pMyObject->Reset((ANSC_HANDLE)pMyObject); */ pMyObject->ExpAllSockets((ANSC_HANDLE)pMyObject); continue; } else if ( !pMyObject->bStarted ) { break; } #endif /* * If there're multiple sockets are receiving data, we loop through the returned fd_set * structure and process them one-by-one. However, we have a slight problem: the resulted * fd_set consists of only the native socket handles, not the associated Socket Objects. * We have to first retrieve the peer's IP address from the socket, and use it to find * the associated socket object. */ #if defined(_ANSC_KERNEL) && defined(_ANSC_LINUX) if (TRUE) { int i; PSINGLE_LINK_ENTRY pSLinkEntry; for ( i = 0; i < ANSC_DETO_SOCKET_TABLE_SIZE ; i++) { if (!AnscSListQueryDepth(&pMyObject->SocketTable[i])) { continue; } AnscAcquireLock(&pMyObject->SocketTableLock); pSLinkEntry = AnscSListGetFirstEntry(&pMyObject->SocketTable[i]); AnscReleaseLock(&pMyObject->SocketTableLock); while ( pSLinkEntry ) { pSocket = ACCESS_ANSC_DAEMON_SOCKET_TCP_OBJECT(pSLinkEntry); pSLinkEntry = AnscSListGetNextEntry(pSLinkEntry); if ( pSocket->bTlsEnabled ) { pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv2 ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; } else { pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; } } if ( !pMyObject->bStarted ) { break; } } AnscSleep(10); } #else for ( i = 0; i < s_result; i++ ) { if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { XSKT_SOCKET_FD_GET(read_fd_set2, s_socket, (ULONG)i); } else { ANSC_SOCKET_FD_GET(read_fd_set1, s_socket, (ULONG)i); } if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_socket == XSKT_SOCKET_INVALID_SOCKET)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_socket == ANSC_SOCKET_INVALID_SOCKET)) ) { break; } else { pSocket = (PANSC_DAEMON_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket ( (ANSC_HANDLE)pMyObject, s_socket ); /* * We should make sure this socket is still valid before proceeding with the socket * receive operations. For example, the peer may have already closed or reset the * TCP connection while we're serving the previous socket request. * * 10/06/04 - It's believed this modification is slowing down the GUI and we're not * seeing tangible evidence that GUI responsivenss has been improved. So we disable * it for now. */ /* if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { XSKT_SOCKET_FD_ZERO(excp_fd_set2); XSKT_SOCKET_FD_SET ((XSKT_SOCKET)s_socket, excp_fd_set2); timeval2.tv_sec = 0; timeval2.tv_usec = 0; s_result_excp = _xskt_select(XSKT_SOCKET_FD_SETSIZE, NULL, NULL, excp_fd_set2, &timeval2); } else { ANSC_SOCKET_FD_ZERO(excp_fd_set1); ANSC_SOCKET_FD_SET (s_socket, excp_fd_set1); timeval1.tv_sec = 0; timeval1.tv_usec = 0; s_result_excp = _ansc_select(ANSC_SOCKET_FD_SETSIZE, NULL, NULL, excp_fd_set1, &timeval1); } */ } /* if ( ((s_result_excp == 1 ) ) || ((s_result_excp == XSKT_SOCKET_ERROR) && (pServer->Mode & ANSC_DSTO_MODE_XSOCKET)) || ((s_result_excp == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_DSTO_MODE_XSOCKET)) ) { if ( TRUE ) { pSocket->bBroken = TRUE; pMyObject->EnableRecv((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE); pMyObject->EnableSend((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE); } if ( pSocket->bTlsEnabled ) { if ( pSocket->bTlsEnabled && pSocket->bTlsConnected && !pSocket->bTlsInitializing ) { returnStatus = pWorker->Notify ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, ANSC_DSTOWO_EVENT_SOCKET_ERROR, (ANSC_HANDLE)NULL ); } else { AnscSetEvent(&pSocket->TlsConnEvent); } } else { returnStatus = pWorker->Notify ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, ANSC_DSTOWO_EVENT_SOCKET_ERROR, (ANSC_HANDLE)NULL ); } if ( pServer->Mode & ANSC_DSTO_MODE_AUTO_CLOSE ) { pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket); } pMyObject->TrcCount++; continue; } else { pSocket = (PANSC_DAEMON_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket ( (ANSC_HANDLE)pMyObject, s_socket ); } */ if ( !pSocket ) { continue; } else if ( pSocket->bTlsEnabled ) { #ifdef _ANSC_USE_OPENSSL_ pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; #else pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv2 ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; #endif } else { pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; } /* * Check whether 'bToBeCleaned' flag is set for this socket: if it is, we should close * this socket right away; otherwise, we continue the processing. WARNING!!! This new * change seems to incur instability in SLAP, we have to roll back to the initial * approach. */ /* if ( pSocket->bToBeCleaned ) { returnStatus = pMyObject->DelSocket ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); } */ if ( !pMyObject->bStarted ) { break; } } #endif } /****************************************************************** GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS ******************************************************************/ EXIT1: AnscSetEvent(&pMyObject->RecvEvent); #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) if ( read_fd_set1 ) { AnscFreeMemory(read_fd_set1); } if ( read_fd_set2 ) { AnscFreeMemory(read_fd_set2); } if ( excp_fd_set1 ) { AnscFreeMemory(excp_fd_set1); } if ( excp_fd_set2 ) { AnscFreeMemory(excp_fd_set2); } #endif return ANSC_STATUS_SUCCESS; }