/*============================================================================ * Create a new signal socket *===========================================================================*/ OpcUa_StatusCode OpcUa_P_SocketManager_NewSignalSocket(OpcUa_SocketManager a_pSocketManager) { OpcUa_InternalSocket* pIntSignalSocket = OpcUa_Null; OpcUa_InternalSocketManager* pInternalSocketManager = (OpcUa_InternalSocketManager*)a_pSocketManager; OpcUa_InitializeStatus(OpcUa_Module_Socket, "NewSignalSocket"); OpcUa_GotoErrorIfArgumentNull(a_pSocketManager); pIntSignalSocket = (OpcUa_InternalSocket*)OpcUa_SocketManager_FindFreeSocket(a_pSocketManager, OpcUa_True); if(pIntSignalSocket == OpcUa_Null) { uStatus = OpcUa_BadResourceUnavailable; goto Error; } uStatus = OpcUa_P_RawSocket_CreateSocketPair( &pIntSignalSocket->rawSocket, &pInternalSocketManager->pCookie); OpcUa_GotoErrorIfBad(uStatus); pIntSignalSocket->Flags.EventMask = OPCUA_SOCKET_CLOSE_EVENT | OPCUA_SOCKET_READ_EVENT | OPCUA_SOCKET_EXCEPT_EVENT | OPCUA_SOCKET_TIMEOUT_EVENT; uStatus = OpcUa_P_RawSocket_SetBlockMode (pIntSignalSocket->rawSocket, OpcUa_False); if (OpcUa_IsBad(uStatus)) { OpcUa_P_RawSocket_Close(pIntSignalSocket->rawSocket); OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); OpcUa_GotoErrorWithStatus(uStatus); } uStatus = OpcUa_P_RawSocket_SetBlockMode (pInternalSocketManager->pCookie, OpcUa_False); if (OpcUa_IsBad(uStatus)) { OpcUa_P_RawSocket_Close(pIntSignalSocket->rawSocket); OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); OpcUa_GotoErrorWithStatus(uStatus); } OPCUA_SOCKET_SETVALID(pIntSignalSocket); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pIntSignalSocket) { pIntSignalSocket->rawSocket = (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID; OPCUA_SOCKET_INVALIDATE(pIntSignalSocket); } OpcUa_FinishErrorHandling; }
/*============================================================================ * Close UDP Socket. *===========================================================================*/ static OpcUa_StatusCode OpcUa_P_SocketService_UdpClose(OpcUa_Socket a_pSocket) { OpcUa_InternalUdpSocket* pInternalSocket = (OpcUa_InternalUdpSocket*)a_pSocket; OpcUa_InitializeStatus(OpcUa_Module_Socket, "UdpClose"); OpcUa_GotoErrorIfArgumentNull(a_pSocket); OpcUa_P_RawSocket_Close(pInternalSocket->rawSocket); OpcUa_P_Memory_Free(pInternalSocket); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * Create a client socket *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_CreateClient( OpcUa_SocketManager a_hSocketManager, OpcUa_StringA a_sRemoteAddress, OpcUa_UInt16 a_uLocalPort, OpcUa_Socket_EventCallback a_pfnSocketCallBack, OpcUa_Void* a_pCallbackData, OpcUa_Socket* a_pSocket) { OpcUa_InternalSocket* pNewClientSocket = OpcUa_Null; OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_UInt16 uPort = 0; OpcUa_StringA sRemoteAdress = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Socket, "CreateClient"); #if !OPCUA_MULTITHREADED if(a_hSocketManager == OpcUa_Null) { a_hSocketManager = OpcUa_Socket_g_SocketManager; } #endif OpcUa_ReturnErrorIfArgumentNull(a_hSocketManager); OpcUa_ReturnErrorIfArgumentNull(a_pSocket); OpcUa_ReturnErrorIfArgumentNull(a_sRemoteAddress); /* parse address */ uStatus = OpcUa_P_ParseUrl( a_sRemoteAddress, &sRemoteAdress, &uPort); OpcUa_ReturnErrorIfBad(uStatus); pInternalSocketManager = (OpcUa_InternalSocketManager*)a_hSocketManager; pNewClientSocket = (OpcUa_InternalSocket*)OpcUa_SocketManager_FindFreeSocket( (OpcUa_SocketManager)pInternalSocketManager, OpcUa_False); if (pNewClientSocket == OpcUa_Null) { OpcUa_P_Memory_Free(sRemoteAdress); uStatus = OpcUa_BadMaxConnectionsReached; /* no socket left in the list. */ goto Error; } /* Create client socket. */ pNewClientSocket->rawSocket = OpcUa_P_Socket_CreateClient( a_uLocalPort, uPort, sRemoteAdress, &uStatus); OpcUa_P_Memory_Free(sRemoteAdress); OpcUa_GotoErrorIfTrue( pNewClientSocket->rawSocket == (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID, OpcUa_BadCommunicationError); pNewClientSocket->pfnEventCallback = a_pfnSocketCallBack; pNewClientSocket->pvUserData = a_pCallbackData; pNewClientSocket->Flags.bOwnThread = OpcUa_False; pNewClientSocket->Flags.EventMask = OPCUA_SOCKET_READ_EVENT | OPCUA_SOCKET_EXCEPT_EVENT | OPCUA_SOCKET_CONNECT_EVENT | OPCUA_SOCKET_TIMEOUT_EVENT; OPCUA_SOCKET_SETVALID(pNewClientSocket); /* return the new client socket */ *a_pSocket = pNewClientSocket; /* break loop to add new socket into eventing */ uStatus = OpcUa_P_SocketManager_InterruptLoop( a_hSocketManager, OPCUA_SOCKET_RENEWLOOP_EVENT, OpcUa_False); OpcUa_GotoErrorIfBad(uStatus); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pNewClientSocket != OpcUa_Null) { if(pNewClientSocket->rawSocket != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close(pNewClientSocket->rawSocket); pNewClientSocket->rawSocket = (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID; } OPCUA_SOCKET_INVALIDATE(pNewClientSocket); } OpcUa_FinishErrorHandling; }
/*============================================================================ * 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; }
/*============================================================================ * Accept Socket connection from Client. *===========================================================================*/ OpcUa_RawSocket OpcUa_P_RawSocket_Accept( OpcUa_RawSocket a_RawSocket, OpcUa_UInt16* a_pPort, OpcUa_UInt32* a_pAddress, OpcUa_Boolean a_bNagleOff, OpcUa_Boolean a_bKeepAliveOn) { int cli_size = 0; int iFlag = 1; SOCKET winSocketServer = (SOCKET)OPCUA_P_SOCKET_INVALID; SOCKET winSocketClient = (SOCKET)OPCUA_P_SOCKET_INVALID; struct sockaddr_in cli; #if OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE || OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE OpcUa_Int iBufferSize = OPCUA_P_TCPRCVBUFFERSIZE; #endif /* OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE || OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE */ if(a_RawSocket == (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { return OpcUa_Null; } winSocketServer = (SOCKET)a_RawSocket; cli_size = sizeof(cli); OpcUa_MemSet(&cli, 0, cli_size); winSocketClient = accept(winSocketServer,(struct sockaddr*) &cli, &cli_size); if(winSocketClient == OPCUA_P_SOCKET_INVALID) { /* accept failed */ goto Error; } if(a_pPort != OpcUa_Null) { *a_pPort = ntohs((OpcUa_UInt16)((struct sockaddr_in*)(&cli))->sin_port); } if(a_pAddress != OpcUa_Null) { *a_pAddress = ((struct sockaddr_in*)(&cli))->sin_addr.s_addr; } if(a_bNagleOff) { /* set socket options */ if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(winSocketClient, IPPROTO_TCP, TCP_NODELAY, (const char*)&iFlag, sizeof(int))) { goto Error; } } if(a_bKeepAliveOn) { /* set socket options */ if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt( winSocketClient, IPPROTO_TCP, SO_KEEPALIVE, (const char*)&iFlag, sizeof(int))) { goto Error; } } #if OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE iBufferSize = OPCUA_P_TCPRCVBUFFERSIZE; if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(winSocketClient, SOL_SOCKET, SO_RCVBUF, (const char*)&iBufferSize, sizeof(int))) { /*int result = OpcUa_P_RawSocket_GetLastError((OpcUa_RawSocket)winSocketClient);*/ goto Error; } #endif /* OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE */ #if OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE iBufferSize = OPCUA_P_TCPSNDBUFFERSIZE; if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(winSocketClient, SOL_SOCKET, SO_SNDBUF, (const char*)&iBufferSize, sizeof(int))) { /*int result = OpcUa_P_RawSocket_GetLastError((OpcUa_RawSocket)winSocketClient);*/ goto Error; } #endif /* OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE */ return (OpcUa_RawSocket)winSocketClient; Error: if(winSocketClient == OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close((OpcUa_RawSocket)winSocketClient); } return (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID; }
/*============================================================================ * Create Socket. *===========================================================================*/ OpcUa_StatusCode OpcUa_P_RawSocket_Create( OpcUa_RawSocket* a_pRawSocket, OpcUa_Boolean a_bNagleOff, OpcUa_Boolean a_bKeepAliveOn) { OpcUa_StatusCode uStatus = OpcUa_Good; int iFlag = 1; OpcUa_Int apiResult = 0; SOCKET WinSocket = (SOCKET)OPCUA_P_SOCKET_INVALID; #if OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE || OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE OpcUa_Int iBufferSize = OPCUA_P_TCPRCVBUFFERSIZE; #endif /* OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE || OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE */ OpcUa_GotoErrorIfArgumentNull(a_pRawSocket); /* create socket through platform API */ WinSocket = socket(AF_INET, SOCK_STREAM, 0); apiResult = OpcUa_P_RawSocket_GetLastError((OpcUa_RawSocket)WinSocket); /* check if socket creation was successful */ if( WinSocket == OPCUA_P_SOCKET_INVALID || apiResult != 0) { uStatus = OpcUa_BadCommunicationError; goto Error; } /* set socketoptions */ if(a_bNagleOff) { if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(WinSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iFlag, sizeof(int))) { uStatus = OpcUa_BadCommunicationError; goto Error; } } if(a_bKeepAliveOn) { /* set socket options */ if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(WinSocket, IPPROTO_TCP, SO_KEEPALIVE, (const char*)&iFlag, sizeof(int))) { uStatus = OpcUa_BadCommunicationError; goto Error; } } #if 0 if(OPCUA_P_SOCKET_SOCKETERROR == getsockopt(WinSocket, SOL_SOCKET, SO_RCVBUF, (char*)&iBufferSize, &temp)) { int result = OpcUa_P_RawSocket_GetLastError((OpcUa_RawSocket)WinSocket); uStatus = OpcUa_BadCommunicationError; goto Error; } #endif #if OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE iBufferSize = OPCUA_P_TCPRCVBUFFERSIZE; if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(WinSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&iBufferSize, sizeof(int))) { /*int result = OpcUa_P_RawSocket_GetLastError((OpcUa_RawSocket)WinSocket);*/ uStatus = OpcUa_BadCommunicationError; goto Error; } #endif /* OPCUA_P_SOCKET_SETTCPRCVBUFFERSIZE */ #if OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE iBufferSize = OPCUA_P_TCPSNDBUFFERSIZE; if(OPCUA_P_SOCKET_SOCKETERROR == setsockopt(WinSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&iBufferSize, sizeof(int))) { /*int result = OpcUa_P_RawSocket_GetLastError((OpcUa_RawSocket)WinSocket);*/ uStatus = OpcUa_BadCommunicationError; goto Error; } #endif /* OPCUA_P_SOCKET_SETTCPSNDBUFFERSIZE */ *a_pRawSocket = (OpcUa_RawSocket)WinSocket; return OpcUa_Good; Error: if(WinSocket != OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close((OpcUa_RawSocket)WinSocket); *a_pRawSocket = (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID; } return uStatus; }