ANSC_HANDLE AnscLpccoPopPendingCall ( ANSC_HANDLE hThisObject, char* party_name, ULONG msg_type, ULONG seq_number, ULONG error_code, ANSC_HANDLE output_bdo ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_LPC_CONNECTOR_OBJECT pMyObject = (PANSC_LPC_CONNECTOR_OBJECT)hThisObject; PANSC_LPCCO_PENDING_CALL pPendingCall = (PANSC_LPCCO_PENDING_CALL )NULL; PSINGLE_LINK_ENTRY pSLinkEntry = (PSINGLE_LINK_ENTRY )NULL; AnscAcquireLock(&pMyObject->PcallQueueLock); pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->PcallQueue); while ( pSLinkEntry ) { pPendingCall = ACCESS_ANSC_LPCCO_PENDING_CALL(pSLinkEntry); pSLinkEntry = AnscQueueGetNextEntry(pSLinkEntry); if ( (pPendingCall->ImcpMsgType == msg_type ) && (pPendingCall->CallSeqNumber == seq_number) ) { if ( party_name && pPendingCall->PartyName ) { if ( !AnscEqualString ( party_name, pPendingCall->PartyName, FALSE ) ) { continue; } } AnscQueuePopEntryByLink(&pMyObject->PcallQueue, &pPendingCall->Linkage); AnscReleaseLock(&pMyObject->PcallQueueLock); if ( TRUE ) { pPendingCall->CallError = error_code; pPendingCall->CallOutputBdo = output_bdo; AnscSetEvent(pPendingCall->CallEvent); } return (ANSC_HANDLE)pPendingCall; } } AnscReleaseLock(&pMyObject->PcallQueueLock); if ( output_bdo ) { AnscFreeBdo(output_bdo); } return (ANSC_HANDLE)NULL; }
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; }
ANSC_STATUS AnscDsuoInitialize ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SERVER_UDP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_UDP_OBJECT)hThisObject; /* * Until you have to simulate C++ object-oriented programming style with standard C, you don't * appreciate all the nice little things come with C++ language and all the dirty works that * have been done by the C++ compilers. Member initialization is one of these things. While in * C++ you don't have to initialize all the member fields inherited from the base class since * the compiler will do it for you, such is not the case with C. */ AnscCoInitialize((ANSC_HANDLE)pMyObject); /* * Although we have initialized some of the member fields in the "create" member function, we * repeat the work here for completeness. While this simulation approach is pretty stupid from * a C++/Java programmer perspective, it's the best we can get for universal embedded network * programming. Before we develop our own operating system (don't expect that to happen any * time soon), this is the way things gonna be. */ pMyObject->Oid = ANSC_DAEMON_SERVER_UDP_OID; pMyObject->Create = AnscDsuoCreate; pMyObject->Remove = AnscDsuoRemove; pMyObject->EnrollObjects = AnscDsuoEnrollObjects; pMyObject->Initialize = AnscDsuoInitialize; pMyObject->Socket = ANSC_SOCKET_INVALID_SOCKET; pMyObject->hWorker = (ANSC_HANDLE)NULL; pMyObject->MaxMessageSize = ANSC_DSUO_MAX_MESSAGE_SIZE; pMyObject->EngineCount = ANSC_DSUO_DEF_ENGINE_COUNT; pMyObject->hNextEngineToUse = (ANSC_HANDLE)NULL; pMyObject->CurSocketCount = 0; pMyObject->MinSocketCount = ANSC_DSUO_MIN_SOCKET_COUNT; pMyObject->MaxSocketCount = ANSC_DSUO_MAX_SOCKET_COUNT; pMyObject->CurPacketCount = 0; pMyObject->MinPacketCount = ANSC_DSUO_MIN_PACKET_COUNT; pMyObject->MaxPacketCount = ANSC_DSUO_MAX_PACKET_COUNT; pMyObject->SocketTimeOut = ANSC_DSUO_SOCKET_TIMEOUT; pMyObject->PacketTimeOut = ANSC_DSUO_PACKET_TIMEOUT; pMyObject->Mode = 0; pMyObject->bActive = FALSE; pMyObject->GetHostAddress = AnscDsuoGetHostAddress; pMyObject->SetHostAddress = AnscDsuoSetHostAddress; pMyObject->GetHostPort = AnscDsuoGetHostPort; pMyObject->SetHostPort = AnscDsuoSetHostPort; pMyObject->GetWorker = AnscDsuoGetWorker; pMyObject->SetWorker = AnscDsuoSetWorker; pMyObject->GetMaxMessageSize = AnscDsuoGetMaxMessageSize; pMyObject->SetMaxMessageSize = AnscDsuoSetMaxMessageSize; pMyObject->GetEngineCount = AnscDsuoGetEngineCount; pMyObject->SetEngineCount = AnscDsuoSetEngineCount; pMyObject->GetMinSocketCount = AnscDsuoGetMinSocketCount; pMyObject->SetMinSocketCount = AnscDsuoSetMinSocketCount; pMyObject->GetMaxSocketCount = AnscDsuoGetMaxSocketCount; pMyObject->SetMaxSocketCount = AnscDsuoSetMaxSocketCount; pMyObject->GetMinPacketCount = AnscDsuoGetMinPacketCount; pMyObject->SetMinPacketCount = AnscDsuoSetMinPacketCount; pMyObject->GetMaxPacketCount = AnscDsuoGetMaxPacketCount; pMyObject->SetMaxPacketCount = AnscDsuoSetMaxPacketCount; pMyObject->GetSocketTimeOut = AnscDsuoGetSocketTimeOut; pMyObject->SetSocketTimeOut = AnscDsuoSetSocketTimeOut; pMyObject->GetPacketTimeOut = AnscDsuoGetPacketTimeOut; pMyObject->SetPacketTimeOut = AnscDsuoSetPacketTimeOut; pMyObject->GetMode = AnscDsuoGetMode; pMyObject->SetMode = AnscDsuoSetMode; pMyObject->Reset = AnscDsuoReset; pMyObject->AcceptTask = AnscDsuoAcceptTask; pMyObject->WorkerTask = AnscDsuoWorkerTask; pMyObject->Engage = AnscDsuoEngage; pMyObject->Cancel = AnscDsuoCancel; pMyObject->StartEngines = AnscDsuoStartEngines; pMyObject->StopEngines = AnscDsuoStopEngines; pMyObject->AcquireSocket = AnscDsuoAcquireSocket; pMyObject->ReleaseSocket = AnscDsuoReleaseSocket; pMyObject->ManufactureSocketPool = AnscDsuoManufactureSocketPool; pMyObject->DestroySocketPool = AnscDsuoDestroySocketPool; pMyObject->AcquirePacket = AnscDsuoAcquirePacket; pMyObject->ReleasePacket = AnscDsuoReleasePacket; pMyObject->ManufacturePacketPool = AnscDsuoManufacturePacketPool; pMyObject->DestroyPacketPool = AnscDsuoDestroyPacketPool; pMyObject->AssignEngine = AnscDsuoAssignEngine; pMyObject->ManufactureEnginePool = AnscDsuoManufactureEnginePool; pMyObject->DestroyEnginePool = AnscDsuoDestroyEnginePool; pMyObject->Query = AnscDsuoQuery; pMyObject->ProcessSync = AnscDsuoProcessSync; pMyObject->ProcessAsync = AnscDsuoProcessAsync; AnscInitializeLock (&pMyObject->OpLock ); AnscInitializeEvent (&pMyObject->AcceptEvent); AnscSetEvent (&pMyObject->AcceptEvent); AnscInitializeLock (&pMyObject->EngineArrayLock); AnscSListInitializeHeader(&pMyObject->SocketSList ); AnscInitializeLock (&pMyObject->SocketSListLock); AnscSListInitializeHeader(&pMyObject->PacketSList ); AnscInitializeLock (&pMyObject->PacketSListLock); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscBetoRecvTask ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_BROKER_ENGINE_TCP_OBJECT pMyObject = (PANSC_BROKER_ENGINE_TCP_OBJECT)hThisObject; PANSC_BROKER_SERVER_TCP_OBJECT pServer = (PANSC_BROKER_SERVER_TCP_OBJECT)pMyObject->hBrokerServer; ansc_fd_set* pRecvSet1 = (ansc_fd_set* )pMyObject->RecvSocketSet; xskt_fd_set* pRecvSet2 = (xskt_fd_set* )pMyObject->RecvSocketSet; PANSC_BROKER_SOCKET_TCP_OBJECT pSocket = NULL; ULONG ulLastCleanAt = AnscGetTickInSeconds(); ANSC_SOCKET s_socket = ANSC_SOCKET_INVALID_SOCKET; int s_result = 0; int s_result_excp = 0; int s_error = 0; int i = 0; uni_fd_set read_fd_set; /*uni_fd_set excp_fd_set;*/ uni_timeval timeval; AnscTrace("AnscBetoRecvTask is activated ...!\n"); /* * 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 ( pMyObject->bCleaningDemanded || (AnscGetTickInSeconds() - ulLastCleanAt) >= ANSC_BETO_CLEAN_TASK_INTERVAL ) { pMyObject->Clean((ANSC_HANDLE)pMyObject); ulLastCleanAt = AnscGetTickInSeconds(); pMyObject->bCleaningDemanded = FALSE; } /* * 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_BSTO_MODE_XSOCKET ) { /* * no need to use lock for read_fd_set here, dirty read does not matter. */ read_fd_set.xset = *pRecvSet2; if( XSKT_SOCKET_FD_ISNUL(&read_fd_set.xset) ) { if ( pServer->Mode & ANSC_BSTO_MODE_EVENT_SYNC ) { AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_BETO_WAIT_EVENT_INTERVAL); AnscResetEvent(&pMyObject->NewSocketEvent); } else { AnscSleep(ANSC_BETO_TASK_BREAK_INTERVAL); } continue; } timeval.xtv.tv_sec = (ANSC_BETO_POLL_INTERVAL_MS / 1000); /* number of seconds */ timeval.xtv.tv_usec = (ANSC_BETO_POLL_INTERVAL_MS % 1000) * 1000; /* number of microseconds */ s_result = _xskt_select(XSKT_SOCKET_FD_SETSIZE, &read_fd_set.xset, NULL, NULL, &timeval.xtv); if ( s_result == 0 ) { continue; } if ( s_result == XSKT_SOCKET_ERROR ) { s_error = _xskt_get_last_error(); pMyObject->Reset((ANSC_HANDLE)pMyObject); continue; } } else { /* * no need to use lock for read_fd_set here, dirty read does not matter. */ read_fd_set.aset = *pRecvSet1; if( ANSC_SOCKET_FD_ISNUL(&read_fd_set.aset) ) { if ( pServer->Mode & ANSC_BSTO_MODE_EVENT_SYNC ) { AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_BETO_WAIT_EVENT_INTERVAL); AnscResetEvent(&pMyObject->NewSocketEvent); } else { AnscSleep(ANSC_BETO_TASK_BREAK_INTERVAL); } continue; } timeval.atv.tv_sec = (ANSC_BETO_POLL_INTERVAL_MS / 1000); /* number of seconds */ timeval.atv.tv_usec = (ANSC_BETO_POLL_INTERVAL_MS % 1000) * 1000; /* number of microseconds */ s_result = _ansc_select(ANSC_SOCKET_FD_SETSIZE, &read_fd_set.aset, NULL, NULL, &timeval.atv); if ( s_result == 0 ) { continue; } if ( s_result == ANSC_SOCKET_ERROR ) { s_error = _ansc_get_last_error(); pMyObject->Reset((ANSC_HANDLE)pMyObject); continue; } } /* * 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. */ for ( i = 0; i < s_result; i++ ) { if ( !pMyObject->bStarted ) { break; } if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET ) { XSKT_SOCKET_FD_GET(&read_fd_set.xset, s_socket, (ULONG)i); if( s_socket == XSKT_SOCKET_INVALID_SOCKET ) { break; } if( ! XSKT_SOCKET_FD_ISSET(s_socket, pRecvSet2) ) { AnscTraceError(("AnscBetoRecvTask: XSKT_SOCKET_FD_ISSET returned FALSE.\n")); continue; } } else { ANSC_SOCKET_FD_GET(&read_fd_set.aset, s_socket, (ULONG)i); if( s_socket == ANSC_SOCKET_INVALID_SOCKET ) { break; } if( ! ANSC_SOCKET_FD_ISSET(s_socket, pRecvSet1) ) { AnscTraceError(("AnscBetoRecvTask: XSKT_SOCKET_FD_ISSET returned FALSE.\n")); continue; } } pSocket = (PANSC_BROKER_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket ( (ANSC_HANDLE)pMyObject, s_socket ); if ( !pSocket ) { continue; } /* * 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. * * 11/20/09 - Re-activate the following code segment to validate the socket before * proceeding. */ /* if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET ) { XSKT_SOCKET_FD_ZERO((&excp_fd_set.xset)); XSKT_SOCKET_FD_SET ((XSKT_SOCKET)s_socket, (&excp_fd_set.xset)); timeval.xtv.tv_sec = 0; timeval.xtv.tv_usec = 0; s_result_excp = _xskt_select(XSKT_SOCKET_FD_SETSIZE, NULL, NULL, &excp_fd_set.xset, &timeval.xtv); } else { ANSC_SOCKET_FD_ZERO((&excp_fd_set.aset)); ANSC_SOCKET_FD_SET (s_socket, (&excp_fd_set.aset)); timeval.atv.tv_sec = 0; timeval.atv.tv_usec = 0; s_result_excp = _ansc_select(ANSC_SOCKET_FD_SETSIZE, NULL, NULL, &excp_fd_set.aset, &timeval.atv); } if ( ((s_result_excp == 1 ) ) || ((s_result_excp == XSKT_SOCKET_ERROR) && (pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) || ((s_result_excp == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) ) { if ( TRUE ) { pSocket->bBroken = TRUE; pSocket->bToBeCleaned = TRUE; pMyObject->EnableRecv((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE); pMyObject->EnableSend((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE); } if ( pServer->Mode & ANSC_BSTO_MODE_AUTO_CLOSE ) { pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket); } continue; } */ returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); } } AnscSetEvent(&pMyObject->RecvEvent); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscSctoTsaNotifyEvent ( ANSC_HANDLE hThisObject, ULONG ulEvent, ULONG ulError, ANSC_HANDLE hEventContext ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_SIMPLE_CLIENT_TCP_OBJECT pMyObject = (PANSC_SIMPLE_CLIENT_TCP_OBJECT)hThisObject; PANSC_SCTO_WORKER_OBJECT pWorker = (PANSC_SCTO_WORKER_OBJECT )pMyObject->hWorker; switch ( ulEvent ) { case TLS_TSA_EVENT_CONNECTION_ESTABLISHED : pMyObject->bTlsConnected = TRUE; AnscSetEvent(&pMyObject->TlsConnEvent); break; case TLS_TSA_EVENT_CONNECTION_CLOSED : pMyObject->bTlsConnected = FALSE; AnscSetEvent(&pMyObject->TlsConnEvent); break; case TLS_TSA_EVENT_CONNECTION_TERMINATED : pMyObject->bBroken = TRUE; if ( pMyObject->bTlsConnected ) { pMyObject->bTlsConnected = FALSE; returnStatus = pWorker->Notify ( pWorker->hWorkerContext, ANSC_SCTOWO_EVENT_TLS_ERROR, (ANSC_HANDLE)ulError ); } else { pMyObject->LastEvent = ANSC_SCTOWO_EVENT_TLS_ERROR; pMyObject->LastError = ulError; AnscSetEvent(&pMyObject->TlsConnEvent); } break; case TLS_TSA_EVENT_CONNECTION_TIMEOUT : pMyObject->bBroken = TRUE; if ( pMyObject->bTlsConnected ) { pMyObject->bTlsConnected = FALSE; returnStatus = pWorker->Notify ( pWorker->hWorkerContext, ANSC_SCTOWO_EVENT_TLS_TIMEOUT, (ANSC_HANDLE)ulError ); } else { pMyObject->LastEvent = ANSC_SCTOWO_EVENT_TLS_TIMEOUT; pMyObject->LastError = ulError; AnscSetEvent(&pMyObject->TlsConnEvent); } break; default : break; } return returnStatus; }