diff options
-rw-r--r-- | Bus/Ivy/ThreadedSocket.cxx | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/Bus/Ivy/ThreadedSocket.cxx b/Bus/Ivy/ThreadedSocket.cxx new file mode 100644 index 0000000..f00e6f5 --- /dev/null +++ b/Bus/Ivy/ThreadedSocket.cxx @@ -0,0 +1,439 @@ +// ThreadedSocket.cpp: implementation of the CThreadedSocket class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include <stddef.h>
+
+#include "ThreadedSocket.h"
+
+
+// Class CThreadedSocketException
+//IMPLEMENT_DYNAMIC(CThreadedSocketException, CException)
+
+CThreadedSocketException::CThreadedSocketException(char* pchMessage)
+{
+ m_strMessage = pchMessage;
+ m_nError = WSAGetLastError();
+}
+
+bool CThreadedSocketException::GetErrorMessage(string & lpstrError, UINT nMaxError,
+ PUINT pnHelpContext /*= NULL*/)
+{
+ lpstrError = m_strMessage;
+ lpstrError += "error";
+ if(m_nError != 0)
+ {
+ lpstrError += " #";
+ lpstrError += m_nError;
+ }
+ return true;
+}
+
+//IMPLEMENT_DYNAMIC(CThreadedSocket, CObject)
+
+bool CThreadedSocket::Initialized = false;
+
+void CThreadedSocket::Init()
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 2 );
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ /* Tell the user that we could not find a usable */
+ /* WinSock DLL. */
+ return;
+ }
+ Initialized = true;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CThreadedSocket::CThreadedSocket()
+{
+ if ( ! Initialized ) Init();
+
+ m_hSocket = INVALID_SOCKET;
+ h_thread = NULL;
+ // Create events to wait on
+ // for receivier part
+ m_hEvent[0] = WSACreateEvent();
+ if ( m_hEvent[0] == WSA_INVALID_EVENT )
+ {
+ TRACE( "CThreadedSocketException(WSACreateEvent )\n");
+ throw( new CThreadedSocketException( "WSACreateEvent" ));
+ }
+ // for transmitter part
+ m_hEvent[1] = WSACreateEvent();
+ if ( m_hEvent[1] == WSA_INVALID_EVENT )
+ {
+ TRACE( "CThreadedSocketException(WSACreateEvent )\n");
+ throw( new CThreadedSocketException( "WSACreateEvent" ));
+ }
+}
+
+CThreadedSocket::~CThreadedSocket()
+{
+ if (m_hSocket != INVALID_SOCKET)
+ Close();
+ //if ( thread ) // On fait de l'auto delete mais dans le cas de terminaison anormale l'object reste ????!!!
+ // delete thread;
+ WSACloseEvent( m_hEvent[0] );
+ WSACloseEvent( m_hEvent[1] );
+}
+void CThreadedSocket::Create(UINT nSocketPort, int nSocketType,
+ long lEvent, const char * lpszSocketAddress)
+{
+ Socket(nSocketType, lEvent);
+ Bind(nSocketPort,lpszSocketAddress);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CThreadedSocket Attributes
+
+
+
+void CThreadedSocket::GetPeerName(string & rPeerAddress, UINT& rPeerPort)
+{
+ SOCKADDR_IN sockAddr;
+ memset(&sockAddr, 0, sizeof(sockAddr));
+
+ int nSockAddrLen = sizeof(sockAddr);
+ GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
+ rPeerPort = ntohs(sockAddr.sin_port);
+ rPeerAddress = inet_ntoa(sockAddr.sin_addr);
+}
+
+void CThreadedSocket::GetSockName(string & rSocketAddress, UINT& rSocketPort)
+{
+ SOCKADDR_IN sockAddr;
+ memset(&sockAddr, 0, sizeof(sockAddr));
+
+ int nSockAddrLen = sizeof(sockAddr);
+ GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
+ rSocketPort = ntohs(sockAddr.sin_port);
+ rSocketAddress = inet_ntoa(sockAddr.sin_addr);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CAscynSocket Operations
+
+void CThreadedSocket::Accept(CThreadedSocket& rConnectedSocket,
+ SOCKADDR* lpSockAddr, int* lpSockAddrLen)
+{
+ assert(rConnectedSocket.m_hSocket == INVALID_SOCKET);
+
+
+ SOCKET hTemp = accept(m_hSocket, lpSockAddr, lpSockAddrLen);
+
+ if (hTemp == INVALID_SOCKET)
+ {
+ rConnectedSocket.m_hSocket = INVALID_SOCKET;
+ throw( new CThreadedSocketException( "accept" ) );
+ }
+ else
+ {
+ rConnectedSocket.m_hSocket = hTemp;
+ rConnectedSocket.StartListener(m_EventMask);
+ }
+}
+
+void CThreadedSocket::Bind(UINT nSocketPort, const char * lpszSocketAddress)
+{
+
+ SOCKADDR_IN sockAddr;
+ memset(&sockAddr,0,sizeof(sockAddr));
+
+ sockAddr.sin_family = AF_INET;
+
+ if (lpszSocketAddress == NULL)
+ sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ else
+ {
+ DWORD lResult = inet_addr(lpszSocketAddress);
+ if (lResult == INADDR_NONE)
+ {
+ WSASetLastError(WSAEINVAL);
+ throw( new CThreadedSocketException( "bind" ) );
+ }
+ sockAddr.sin_addr.s_addr = lResult;
+ }
+
+ sockAddr.sin_port = htons((u_short)nSocketPort);
+
+ Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr));
+}
+
+void CThreadedSocket::Close()
+{
+ if (m_hSocket != INVALID_SOCKET)
+ {
+ AsyncSelect(0);
+ assert(SOCKET_ERROR != closesocket(m_hSocket));
+ m_hSocket = INVALID_SOCKET;
+ //WSASetEvent( m_hEventObject );
+ }
+}
+
+bool CThreadedSocket::Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen)
+{
+ if ( !connect(m_hSocket, lpSockAddr, nSockAddrLen) )
+ {
+ DWORD err = WSAGetLastError();
+ if ( err == 0 ) return TRUE;
+ TRACE( "***************************************Error connect %d\n", err);
+ if ( err != WSAEWOULDBLOCK )
+ return FALSE;
+ // Wait for connection to complete
+ TRACE( "***************************************Waiting for connection to complete\n");
+ err = WSAWaitForMultipleEvents( 1, m_hEvent, FALSE, WSA_INFINITE, TRUE);
+ //TRACE( "Thread socket %d wait return %d\n", m_hSocket, err );
+ if ( err == WSA_WAIT_FAILED )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ return TRUE;
+}
+
+bool CThreadedSocket::Connect(const char * lpszHostAddress, UINT nHostPort)
+{
+
+ assert(lpszHostAddress != NULL);
+
+ SOCKADDR_IN sockAddr;
+ memset(&sockAddr,0,sizeof(sockAddr));
+
+ sockAddr.sin_family = AF_INET;
+ sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress);
+
+ if (sockAddr.sin_addr.s_addr == INADDR_NONE)
+ {
+ LPHOSTENT lphost;
+ lphost = gethostbyname(lpszHostAddress);
+ if (lphost != NULL)
+ sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
+ else
+ {
+ WSASetLastError(WSAEINVAL);
+ return FALSE;
+ }
+ }
+
+ sockAddr.sin_port = htons((u_short)nHostPort);
+
+ return Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
+}
+
+int CThreadedSocket::Receive(void* lpBuf, int nBufLen, int nFlags)
+{
+ int lg = recv(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
+ if ( lg == SOCKET_ERROR )
+ throw( new CThreadedSocketException( "recv" ) );
+ return lg;
+}
+
+int CThreadedSocket::ReceiveFrom(void* lpBuf, int nBufLen, string & rSocketAddress, UINT& rSocketPort, int nFlags)
+{
+ SOCKADDR_IN sockAddr;
+
+ memset(&sockAddr, 0, sizeof(sockAddr));
+
+ int nSockAddrLen = sizeof(sockAddr);
+ int nResult = ReceiveFrom(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, &nSockAddrLen, nFlags);
+ rSocketPort = ntohs(sockAddr.sin_port);
+ rSocketAddress = inet_ntoa(sockAddr.sin_addr);
+
+ return nResult;
+}
+
+void CThreadedSocket::Send(const void* lpBuf, int nBufLen, int nFlags)
+{
+ if ( send(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags) != nBufLen )
+ throw( new CThreadedSocketException( "send" ) );
+}
+
+void CThreadedSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, const char * lpszHostAddress, int nFlags)
+{
+ SOCKADDR_IN sockAddr;
+
+ memset(&sockAddr,0,sizeof(sockAddr));
+
+ sockAddr.sin_family = AF_INET;
+
+ if (lpszHostAddress == NULL)
+ sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
+ else
+ {
+ sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress);
+ if (sockAddr.sin_addr.s_addr == INADDR_NONE)
+ {
+ LPHOSTENT lphost;
+ lphost = gethostbyname(lpszHostAddress);
+ if (lphost != NULL)
+ sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
+ else
+ {
+ WSASetLastError(WSAEINVAL);
+ throw( new CThreadedSocketException( "SendTo" ));
+ return;
+ }
+ }
+ }
+
+ sockAddr.sin_port = htons((u_short)nHostPort);
+
+ SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags);
+}
+void CThreadedSocket::AsyncSelect(long lEvent)
+{
+ assert(m_hSocket != INVALID_SOCKET);
+ if ( WSAEventSelect(m_hSocket, m_hEvent[0], lEvent) )
+ throw( new CThreadedSocketException( "WSAEventSelect" ));
+}
+/////////////////////////////////////////////////////////////////////////////
+// CThreadedSocket Overridable callbacks
+void CThreadedSocket::OnWakeup()
+{
+}
+void CThreadedSocket::OnReceive(int /*nErrorCode*/)
+{
+}
+
+void CThreadedSocket::OnSend(int /*nErrorCode*/)
+{
+}
+
+void CThreadedSocket::OnOutOfBandData(int /*nErrorCode*/)
+{
+}
+
+void CThreadedSocket::OnAccept(int /*nErrorCode*/)
+{
+}
+
+void CThreadedSocket::OnConnect(int /*nErrorCode*/)
+{
+}
+
+void CThreadedSocket::OnClose(int /*nErrorCode*/)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CThreadedSocket Implementation
+
+
+void CThreadedSocket::Socket(int nSocketType, long lEvent, int nProtocolType, int nAddressFormat)
+{
+ assert(m_hSocket == INVALID_SOCKET);
+
+ m_hSocket = socket(nAddressFormat,nSocketType,nProtocolType);
+// m_hSocket = WSASocket ( nAddressFormat, nSocketType,nProtocolType, NULL, 0, 0 );
+
+
+ if (m_hSocket == INVALID_SOCKET)
+ {
+ throw( new CThreadedSocketException( "socket" ));
+ }
+ StartListener(lEvent);
+
+}
+
+void CThreadedSocket::StartListener(long lEvent)
+{
+ m_EventMask = lEvent;
+ h_thread = CreateThread(NULL,0,SocketThreadProc, this, 0, &thread_id);
+ if ( ! h_thread )
+ throw( new CThreadedSocketException( "socket listener" ));
+}
+// Implementation
+DWORD WINAPI CThreadedSocket::SocketThreadProc( LPVOID pParam )
+{
+ CThreadedSocket* pObject = (CThreadedSocket*)pParam;
+
+ if (pObject == NULL )
+ {
+ throw( new CThreadedSocketException( "bad socket proc" ));
+ return -1; // if pObject is not valid
+ }
+
+ return pObject->SocketThread();
+}
+
+UINT CThreadedSocket::SocketThread( )
+{
+ DWORD err;
+ WSANETWORKEVENTS NetworkEvents;
+
+ AsyncSelect(m_EventMask) ;
+ while ( m_hSocket != INVALID_SOCKET )
+ {
+ err = WSAWaitForMultipleEvents( 2, m_hEvent, FALSE, WSA_INFINITE, TRUE);
+ switch ( err )
+ {
+ case WSA_WAIT_FAILED:
+ TRACE( "CThreadedSocketException(WSAWaitForMultipleEvents )\n");
+ throw( new CThreadedSocketException( "WSAWaitForMultipleEvents" ));
+ return err;
+ break;
+ case WSA_WAIT_EVENT_0:
+
+ NetworkEvents.lNetworkEvents=0;
+
+ if ( WSAEnumNetworkEvents ( m_hSocket, m_hEvent[0], &NetworkEvents ))
+ {
+ TRACE( "CThreadedSocketException(WSAEnumNetworkEvents )\n");
+ throw( new CThreadedSocketException( "WSAEnumNetworkEvents" ));
+ return -1;
+ }
+
+
+ if ( NetworkEvents.lNetworkEvents & FD_READ )
+ OnReceive(NetworkEvents.iErrorCode[ FD_READ_BIT ]);
+
+ if ( NetworkEvents.lNetworkEvents & FD_WRITE )
+ OnSend( NetworkEvents.iErrorCode[ FD_WRITE_BIT ] );
+
+ if ( NetworkEvents.lNetworkEvents & FD_ACCEPT )
+ OnAccept( NetworkEvents.iErrorCode[ FD_ACCEPT_BIT ] );
+
+
+ if ( NetworkEvents.lNetworkEvents & FD_CONNECT )
+ OnConnect( NetworkEvents.iErrorCode[ FD_CONNECT_BIT ] );
+
+ if ( NetworkEvents.lNetworkEvents & FD_OOB )
+ OnOutOfBandData( NetworkEvents.iErrorCode[ FD_OOB_BIT ] );
+
+ if ( NetworkEvents.lNetworkEvents & FD_CLOSE )
+ {
+ OnClose( NetworkEvents.iErrorCode[ FD_CLOSE_BIT ] );
+ }
+
+ break;
+ case WSA_WAIT_EVENT_0 +1 :
+ if ( m_hSocket != INVALID_SOCKET )
+ {
+ OnWakeup();
+ }
+ // else Close by other Thread do silent terminaison
+ WSAResetEvent( m_hEvent[1] );
+
+ break;
+ default:
+ TRACE( "CThreadedSocket::SocketThread Unhandled Events !\n");
+ break;
+ }
+ }
+ Close();
+ h_thread = NULL;
+ return 0;
+}
|