/* HINT: That is a thread entry point and wrapper for the real serverloop. */ OpcUa_Void OpcUa_P_SocketManager_ServerLoopThread(OpcUa_Void* a_pArgument) { OpcUa_StatusCode uStatus = OpcUa_Good; /* only needed for internal reasons */ OpcUa_InternalSocketManager* pInternalSocketManager = (OpcUa_InternalSocketManager*)a_pArgument; OpcUa_Int32 iSocketManagerSlot; OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "NetworkThread: Message Loop started...\n"); do { uStatus = OpcUa_P_SocketManager_ServeLoopInternal( pInternalSocketManager, OpcUa_UInt32_Max, OpcUa_False); if(OpcUa_IsEqual(OpcUa_GoodShutdownEvent)) { /* leave this loop if a shutdown was signalled */ break; } } while(OpcUa_IsGood(uStatus)); /* Debug Output */ OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "NetworkThread: Message Loop shutting down! (0x%08X)\n", uStatus); if(pInternalSocketManager->Flags.bSpawnThreadOnAccept != 0) { #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Lock(pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ for(iSocketManagerSlot = 0; iSocketManagerSlot < OPCUA_SOCKET_MAXMANAGERS; iSocketManagerSlot++) { if(pInternalSocketManager->pSocketManagers[iSocketManagerSlot] != OpcUa_Null) { OpcUa_InternalSocketManager *pSpawnedSocketManager = pInternalSocketManager->pSocketManagers[iSocketManagerSlot]; pInternalSocketManager->pSocketManagers[iSocketManagerSlot] = OpcUa_Null; pSpawnedSocketManager->pThreadToJoin = pInternalSocketManager->pThreadToJoin; pInternalSocketManager->pThreadToJoin = pSpawnedSocketManager->pThread; pSpawnedSocketManager->pThread = OpcUa_Null; OpcUa_P_SocketManager_InterruptLoop(pSpawnedSocketManager, OPCUA_SOCKET_SHUTDOWN_EVENT, OpcUa_False); } } #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Unlock(pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ if(pInternalSocketManager->pThreadToJoin != OpcUa_Null) { OpcUa_P_Thread_Delete(&pInternalSocketManager->pThreadToJoin); } } return; }
/*============================================================================ * Delete *===========================================================================*/ OpcUa_Void OpcUa_Thread_Delete(OpcUa_Thread* a_pThread) { OpcUa_ThreadInternal* pThread = OpcUa_Null; if(a_pThread == OpcUa_Null || *a_pThread == OpcUa_Null) { return; } pThread = *((OpcUa_ThreadInternal**)a_pThread); if(pThread->IsRunning != OpcUa_False) { return; } if(pThread->ShutdownEvent) { OPCUA_P_SEMAPHORE_DELETE(&(pThread->ShutdownEvent)); } if(pThread->RawThread) { OpcUa_P_Thread_Delete(&(pThread->RawThread)); } if(pThread->Mutex) { OPCUA_P_MUTEX_DELETE(&(pThread->Mutex)); } pThread->ThreadData = OpcUa_Null; pThread->ThreadMain = OpcUa_Null; OpcUa_Free(*a_pThread); *a_pThread = OpcUa_Null; return; }
/*============================================================================ * Delete SocketManager Type (closes all sockets) *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_SocketManager_Delete(OpcUa_SocketManager* a_pSocketManager) { OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_UInt32 uintIndex = 0; #if !OPCUA_MULTITHREADED if(a_pSocketManager == OpcUa_Null && OpcUa_Socket_g_SocketManager != OpcUa_Null) { a_pSocketManager = &OpcUa_Socket_g_SocketManager; } #endif if(a_pSocketManager == OpcUa_Null || *a_pSocketManager == OpcUa_Null) { OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "OpcUa_SocketManager_Delete: Invalid Socket Manager!\n"); return; } pInternalSocketManager = (OpcUa_InternalSocketManager*)*a_pSocketManager; /* send shutdown event to serveloop */ OpcUa_P_SocketManager_InterruptLoop(pInternalSocketManager, OPCUA_SOCKET_SHUTDOWN_EVENT, OpcUa_False); #if OPCUA_MULTITHREADED if(pInternalSocketManager->pThread != OpcUa_Null) { OpcUa_P_Thread_Delete(&(pInternalSocketManager->pThread)); } else { OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "OpcUa_SocketManager_Delete: Invalid Thread Handle!\n"); return; } #endif /* OPCUA_MULTITHREADED */ #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Lock(pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ /* handle the socket list content (close, cleanup, etc.) */ if(pInternalSocketManager->pSockets != OpcUa_Null) { for(uintIndex = 0; uintIndex < pInternalSocketManager->uintMaxSockets; uintIndex++) { OpcUa_Socket pSocketTemp = &(pInternalSocketManager->pSockets[uintIndex]); if( (pInternalSocketManager->pSockets[uintIndex].bSocketIsInUse != OpcUa_False) && (pInternalSocketManager->pSockets[uintIndex].bInvalidSocket == OpcUa_False)) { OpcUa_Socket_HandleEvent(pSocketTemp, OPCUA_SOCKET_CLOSE_EVENT); OpcUa_P_RawSocket_Close(pInternalSocketManager->pSockets[uintIndex].rawSocket); } OpcUa_Socket_Clear(pSocketTemp); } OpcUa_P_Memory_Free(pInternalSocketManager->pSockets); } /* if(pInternalSocketManager->pSockets != OpcUa_Null) */ OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Unlock(pInternalSocketManager->pMutex); OpcUa_P_Mutex_Delete(&pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ #if OPCUA_MULTITHREADED if(pInternalSocketManager->pStartupSemaphore != OpcUa_Null) { OpcUa_P_Semaphore_Delete(&pInternalSocketManager->pStartupSemaphore); } if(pInternalSocketManager->pSocketManagers != OpcUa_Null) { OpcUa_P_Memory_Free(pInternalSocketManager->pSocketManagers); } #endif OpcUa_P_Memory_Free(*a_pSocketManager); *a_pSocketManager = OpcUa_Null; return; }
/*============================================================================ * Create a new socket manager or initialize the global one (OpcUa_Null first). *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_Create(OpcUa_SocketManager* a_pSocketManager, OpcUa_UInt32 a_nSockets, OpcUa_UInt32 a_nFlags) { OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Socket, "SocketManager_Create"); if(a_nFlags & 0xFFFFFFF8) { return OpcUa_BadInvalidArgument; } if(a_nSockets > OPCUA_P_SOCKETMANAGER_NUMBEROFSOCKETS) { return OpcUa_BadInvalidArgument; } /* set number of socket to maximum */ if(a_nSockets == 0) { a_nSockets = OPCUA_P_SOCKETMANAGER_NUMBEROFSOCKETS; } a_nSockets += 1; /* add signal socket to requested sockets */ #if !OPCUA_MULTITHREADED if(a_pSocketManager == OpcUa_Null && OpcUa_Socket_g_SocketManager == OpcUa_Null) { a_pSocketManager = &OpcUa_Socket_g_SocketManager; } #endif if(a_pSocketManager == OpcUa_Null) { return OpcUa_BadInvalidArgument; } *a_pSocketManager = OpcUa_SocketManager_Alloc(); OpcUa_GotoErrorIfAllocFailed(*a_pSocketManager); pInternalSocketManager = (OpcUa_InternalSocketManager*)*a_pSocketManager; OpcUa_SocketManager_Initialize(pInternalSocketManager); #if OPCUA_USE_SYNCHRONISATION uStatus = OpcUa_P_Mutex_Create(&pInternalSocketManager->pMutex); OpcUa_GotoErrorIfBad(uStatus); #endif /* OPCUA_USE_SYNCHRONISATION */ /* preallocate socket structures for all possible sockets (maxsockets) */ uStatus = OpcUa_SocketManager_CreateSockets((OpcUa_SocketManager)pInternalSocketManager, a_nSockets); OpcUa_GotoErrorIfBad(uStatus); pInternalSocketManager->uintLastExternalEvent = OPCUA_SOCKET_NO_EVENT; /* set the behaviour flags */ if((a_nFlags & OPCUA_SOCKET_SPAWN_THREAD_ON_ACCEPT) != OPCUA_SOCKET_NO_FLAG) { pInternalSocketManager->Flags.bSpawnThreadOnAccept = OpcUa_True; } if((a_nFlags & OPCUA_SOCKET_REJECT_ON_NO_THREAD) != OPCUA_SOCKET_NO_FLAG) { pInternalSocketManager->Flags.bRejectOnThreadFail = OpcUa_True; } if((a_nFlags & OPCUA_SOCKET_DONT_CLOSE_ON_EXCEPT) != OPCUA_SOCKET_NO_FLAG) { pInternalSocketManager->Flags.bDontCloseOnExcept = OpcUa_True; } uStatus = OpcUa_P_SocketManager_NewSignalSocket(pInternalSocketManager); OpcUa_GotoErrorIfBad(uStatus); #if OPCUA_MULTITHREADED if (pInternalSocketManager->Flags.bSpawnThreadOnAccept) { /* create a semaphore with no free resources for which a host can wait to be signalled. */ uStatus = OpcUa_P_Semaphore_Create(&pInternalSocketManager->pStartupSemaphore, 0, 1); OpcUa_GotoErrorIfBad(uStatus); pInternalSocketManager->pSocketManagers = OpcUa_P_Memory_Alloc(sizeof(OpcUa_InternalSocketManager*) * OPCUA_SOCKET_MAXMANAGERS); OpcUa_GotoErrorIfAllocFailed(pInternalSocketManager->pSocketManagers); OpcUa_MemSet(pInternalSocketManager->pSocketManagers, 0, sizeof(OpcUa_InternalSocketManager*) * OPCUA_SOCKET_MAXMANAGERS); } /* if multithreaded, create and start the server thread if the list is not the global list. */ uStatus = OpcUa_P_Thread_Create(&pInternalSocketManager->pThread); /* make raw thread */ OpcUa_GotoErrorIfBad(uStatus); uStatus = OpcUa_P_Thread_Start( pInternalSocketManager->pThread, OpcUa_P_SocketManager_ServerLoopThread, (OpcUa_Void*)pInternalSocketManager); OpcUa_GotoErrorIfBad(uStatus); #endif /* OPCUA_MULTITHREADED */ OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pInternalSocketManager != OpcUa_Null) { #if OPCUA_MULTITHREADED if(pInternalSocketManager->pThread != OpcUa_Null) { OpcUa_P_Thread_Delete(&pInternalSocketManager->pThread); } if(pInternalSocketManager->pSocketManagers != OpcUa_Null) { OpcUa_P_Memory_Free(pInternalSocketManager->pSocketManagers); } if(pInternalSocketManager->pStartupSemaphore != OpcUa_Null) { OpcUa_P_Semaphore_Delete(&pInternalSocketManager->pStartupSemaphore); } #endif /* OPCUA_MULTITHREADED */ if(pInternalSocketManager->pCookie != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); } if(pInternalSocketManager->pSockets != OpcUa_Null) { if(pInternalSocketManager->pSockets[0].rawSocket != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close(pInternalSocketManager->pSockets[0].rawSocket); } OpcUa_P_Memory_Free(pInternalSocketManager->pSockets); } #if OPCUA_USE_SYNCHRONISATION if(pInternalSocketManager->pMutex != OpcUa_Null) { OpcUa_P_Mutex_Delete(&pInternalSocketManager->pMutex); } #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_P_Memory_Free(pInternalSocketManager); } *a_pSocketManager = OpcUa_Null; OpcUa_FinishErrorHandling; }