Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / TOF / Win32++ / include / socket.h
diff --git a/research/transmission_spectroscopy/TOF/Win32++/include/socket.h b/research/transmission_spectroscopy/TOF/Win32++/include/socket.h
new file mode 100644 (file)
index 0000000..e7e1b89
--- /dev/null
@@ -0,0 +1,778 @@
+// Win32++   Version 7.3\r
+// Released: 30th November 2011\r
+//\r
+//      David Nash\r
+//      email: [email protected]\r
+//      url: https://sourceforge.net/projects/win32-framework\r
+//\r
+//\r
+// Copyright (c) 2005-2011  David Nash\r
+//\r
+// Permission is hereby granted, free of charge, to\r
+// any person obtaining a copy of this software and\r
+// associated documentation files (the "Software"),\r
+// to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify,\r
+// merge, publish, distribute, sublicense, and/or sell\r
+// copies of the Software, and to permit persons to whom\r
+// the Software is furnished to do so, subject to the\r
+// following conditions:\r
+//\r
+// The above copyright notice and this permission notice\r
+// shall be included in all copies or substantial portions\r
+// of the Software.\r
+//\r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\r
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\r
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\r
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\r
+// OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+////////////////////////////////////////////////////////\r
+\r
+\r
+////////////////////////////////////////////////////////\r
+// socket.h\r
+//  Declaration of the CSocket class\r
+//\r
+// The CSocket class represents a network socket. It encapsualtes many of\r
+// the Windows Socket SPI fuctions, providing an object-oriented approach\r
+// to network programming. After StartEvents is called, CSocket monitors\r
+// the socket and responds automatically to network events. This event\r
+// monitoring, for example, automatically calls OnReceive when there is\r
+// data on the socket to be read, and OnAccept when a server should accept\r
+// a connection from a client.\r
+\r
+// Users of this class should be aware that functions like OnReceive,\r
+// OnAccept, etc. are called on a different thread from the one CSocket is\r
+// instanciated on. The thread for these functions needs to respond quickly\r
+// to other network events, so it shouldn't be delayed. It also doesn't run\r
+// a message loop, so it can't be used to create windows. For these reasons\r
+// it might be best to use PostMessage in response to these functions in a\r
+// windows environment.\r
+\r
+// Refer to the network samples for an example of how to use this class to\r
+// create a TCP client & server, and a UDP client and server.\r
+\r
+// To compile programs with CSocket, link with ws3_32.lib for Win32,\r
+// and ws2.lib for Windows CE. Windows 95 systems will need to install the\r
+// "Windows Sockets 2.0 for Windows 95". It's available from:\r
+// http://support.microsoft.com/kb/182108/EN-US/\r
+\r
+// For a TCP server, inherit a class from CSocket and override OnAccept, OnDisconnect\r
+// and OnRecieve. Create one instance of this class and use it as a listening socket.\r
+// The purpose of the listening socket is to detect connections from clients and accept them.\r
+// For the listening socket, we do the following:\r
+// 1) Create the socket.\r
+// 2) Bind an IP address to the socket.\r
+// 3) Listen on the socket for incoming connection requests.\r
+// 4) Use StartNotifyRevents to receive notification of network events.\r
+// 5) Override OnAccept to accept requests on a newly created data CSocket object.\r
+// 6) Create a new data socket for each client connection accepted.\r
+// 7) The server socket uses the 'accept' function to accept an incoming connection\r
+//     from this new data socket.\r
+\r
+// The purpose of the data socket is to send data to, and recieve data from the client.\r
+// There will be one data socket for each client accepted by the server.\r
+// To use it we do the following:\r
+// * To recieve data from the client, override OnReceive and use Receive.\r
+// * To send data to use Send.\r
+// * OnDisconnect can be used to detect when the client is disconnected.\r
+\r
+// For a TCP client, inherit from CSocket and override OnReceive and OnDisconnect.\r
+// Create an instance of this inherited class, and  perform the following steps:\r
+// 1) Create the socket.\r
+// 2) Connect to the server.\r
+// 3) Use StartNotifyRevents to receive notification of network events.\r
+//    We are now ready to send and recieve data from the server.\r
+// * Use Send to send data to the server.\r
+// * Override OnReceive and use Recieve to receive data from the server\r
+// * OnDisconnect can be used to detect when the client is disconnected from the server.\r
+\r
+// Notes regarding IPv6 support\r
+// * IPv6 is supported on Windows Vista and above. Windows XP with SP2 provides\r
+//    "experimental" support, which can be enabled by entering "ipv6 install"\r
+//    at a command prompt.\r
+// * IPv6 is not supported by all compilters and devlopment environments. In\r
+//    particular, it is not supported by Dev-C++ or Borland 5.5. A modern\r
+//    Platform SDK needs to be added to Visual Studio 6 for it to support IPv6.\r
+// * IsIPV6Supported returns false if either the operating system or the\r
+//    development environment fails to support IPv6.\r
+//\r
+\r
+#ifndef _WIN32XX_SOCKET_H_\r
+#define _WIN32XX_SOCKET_H_\r
+\r
+\r
+#include "wincore.h"\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h>\r
+#include <process.h>\r
+\r
+\r
+#define THREAD_TIMEOUT 100\r
+\r
+\r
+namespace Win32xx\r
+{\r
+\r
+       typedef int  WINAPI GETADDRINFO(LPCSTR, LPCSTR, const struct addrinfo*, struct addrinfo**);\r
+       typedef void WINAPI FREEADDRINFO(struct addrinfo*);\r
+\r
+       class CSocket\r
+       {\r
+       public:\r
+               CSocket();\r
+               virtual ~CSocket();\r
+\r
+               // Operations\r
+               virtual void Accept(CSocket& rClientSock, struct sockaddr* addr, int* addrlen);\r
+               virtual int  Bind(LPCTSTR addr, LPCTSTR port);\r
+               virtual int  Bind(const struct sockaddr* name, int namelen);\r
+               virtual int  Connect(LPCTSTR addr, LPCTSTR port);\r
+               virtual int  Connect(const struct sockaddr* name, int namelen);\r
+               virtual bool Create( int family, int type, int protocol = IPPROTO_IP);\r
+               virtual void Disconnect();\r
+               virtual void FreeAddrInfo( struct addrinfo* ai );\r
+               virtual int  GetAddrInfo( LPCTSTR nodename, LPCTSTR servname, const struct addrinfo* hints, struct addrinfo** res);\r
+               virtual LPCTSTR GetLastError();\r
+               virtual int  ioCtlSocket(long cmd, u_long* argp);\r
+               virtual bool IsIPV6Supported();\r
+               virtual int  Listen(int backlog = SOMAXCONN);\r
+               virtual int  Receive(TCHAR* buf, int len, int flags);\r
+               virtual int  ReceiveFrom(TCHAR* buf, int len, int flags, struct sockaddr* from, int* fromlen);\r
+               virtual int  Send(LPCTSTR buf, int len, int flags);\r
+               virtual int  SendTo(LPCTSTR send, int len, int flags, LPCTSTR addr, LPCTSTR port);\r
+               virtual int  SendTo(LPCTSTR buf, int len, int flags, const struct sockaddr* to, int tolen);\r
+\r
+               virtual void StartEvents();\r
+               virtual void StopEvents();\r
+\r
+               // Attributes\r
+               virtual int  GetPeerName(struct sockaddr* name, int* namelen);\r
+               virtual int  GetSockName(struct sockaddr* name, int* namelen);\r
+               SOCKET& GetSocket() { return m_Socket; }\r
+               virtual int  GetSockOpt(int level, int optname, char* optval, int* optlen);\r
+               virtual int  SetSockOpt(int level, int optname, const char* optval, int optlen);\r
+\r
+               // Override these functions to monitor events\r
+               virtual void OnAccept()         {}\r
+               virtual void OnAddresListChange() {}\r
+               virtual void OnDisconnect()     {}\r
+               virtual void OnConnect()        {}\r
+               virtual void OnOutOfBand()      {}\r
+               virtual void OnQualityOfService() {}\r
+               virtual void OnReceive()        {}\r
+               virtual void OnRoutingChange() {}\r
+               virtual void OnSend()           {}\r
+\r
+\r
+\r
+               // Allow CSocket to be used as a SOCKET\r
+               operator SOCKET() const {return m_Socket;}\r
+\r
+       private:\r
+               CSocket(const CSocket&);                                // Disable copy construction\r
+               CSocket& operator = (const CSocket&);   // Disable assignment operator\r
+               static UINT WINAPI EventThread(LPVOID thread_data);\r
+\r
+               CString m_ErrorMessage;\r
+               SOCKET m_Socket;\r
+               HMODULE m_hWS2_32;\r
+               HANDLE m_hEventThread;  // Handle to the thread\r
+               HANDLE m_StopRequest;   // An event to signal the event thread should stop\r
+               HANDLE m_Stopped;               // An event to signal the event thread is stopped\r
+\r
+               GETADDRINFO* m_pfnGetAddrInfo;          // pointer for the GetAddrInfo function\r
+               FREEADDRINFO* m_pfnFreeAddrInfo;        // pointer for the FreeAddrInfo function\r
+       };\r
+}\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+namespace Win32xx\r
+{\r
+\r
+       inline CSocket::CSocket() : m_Socket(INVALID_SOCKET), m_hEventThread(0)\r
+       {\r
+               // Initialise the Windows Socket services\r
+               WSADATA wsaData;\r
+\r
+               if (0 != ::WSAStartup(MAKEWORD(2,2), &wsaData))\r
+                       throw CWinException(_T("WSAStartup failed"));\r
+\r
+               m_hWS2_32 = ::LoadLibrary(_T("WS2_32.dll"));\r
+               if (0 == m_hWS2_32)\r
+                       throw CWinException(_T("Failed to load WS2_2.dll"));\r
+\r
+               m_pfnGetAddrInfo = (GETADDRINFO*) GetProcAddress(m_hWS2_32, "getaddrinfo");\r
+               m_pfnFreeAddrInfo = (FREEADDRINFO*) GetProcAddress(m_hWS2_32, "freeaddrinfo");\r
+\r
+               m_StopRequest = ::CreateEvent(0, TRUE, FALSE, 0);\r
+               m_Stopped = ::CreateEvent(0, TRUE, FALSE, 0);\r
+       }\r
+\r
+       inline CSocket::~CSocket()\r
+       {\r
+               Disconnect();\r
+\r
+               // Close handles\r
+               ::CloseHandle(m_StopRequest);\r
+               ::CloseHandle(m_Stopped);\r
+\r
+               // Terminate the  Windows Socket services\r
+               ::WSACleanup();\r
+\r
+               ::FreeLibrary(m_hWS2_32);\r
+       }\r
+\r
+       inline void CSocket::Accept(CSocket& rClientSock, struct sockaddr* addr, int* addrlen)\r
+       {\r
+               // The accept function permits an incoming connection attempt on the socket.\r
+\r
+               rClientSock.m_Socket = ::accept(m_Socket, addr, addrlen);\r
+               if (INVALID_SOCKET == rClientSock.GetSocket())\r
+                       TRACE(_T("Accept failed\n"));\r
+       }\r
+\r
+       inline int CSocket::Bind(LPCTSTR addr, LPCTSTR port)\r
+       // The bind function associates a local address with the socket.\r
+       {\r
+               int RetVal = 0;\r
+\r
+               if (IsIPV6Supported())\r
+               {\r
+\r
+#ifdef GetAddrInfo     // Skip the following code block for older development environments\r
+\r
+                       ADDRINFO Hints= {0};\r
+                       Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;\r
+                       ADDRINFO *AddrInfo;\r
+\r
+                       RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);\r
+                       if (RetVal != 0)\r
+                       {\r
+                               TRACE( _T("GetAddrInfo failed\n"));\r
+                               return RetVal;\r
+                       }\r
+\r
+                       // Bind the IP address to the listening socket\r
+                       RetVal =  ::bind( m_Socket, AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );\r
+                       if ( RetVal == SOCKET_ERROR )\r
+                       {\r
+                               TRACE(_T("Bind failed\n"));\r
+                               return RetVal;\r
+                       }\r
+\r
+                       // Free the address information allocated by GetAddrInfo\r
+                       FreeAddrInfo(AddrInfo);\r
+\r
+#endif\r
+\r
+               }\r
+               else\r
+               {\r
+                       sockaddr_in clientService;\r
+                       clientService.sin_family = AF_INET;\r
+                       clientService.sin_addr.s_addr = inet_addr( T2A(addr) );\r
+                       int nPort = -1;\r
+            nPort = atoi( T2A(port) );\r
+                       if (-1 == nPort)\r
+                       {\r
+                               TRACE(_T("Invalid port number\n"));\r
+                               return SOCKET_ERROR;\r
+                       }\r
+                       clientService.sin_port = htons( (u_short)nPort );\r
+\r
+                       RetVal = ::bind( m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) );\r
+                       if ( 0 != RetVal )\r
+                               TRACE(_T("Bind failed\n"));\r
+               }\r
+\r
+               return RetVal;\r
+       }\r
+\r
+       inline int CSocket::Bind(const struct sockaddr* name, int namelen)\r
+       {\r
+               // The bind function associates a local address with the socket.\r
+\r
+               int Result = ::bind (m_Socket, name, namelen);\r
+               if ( 0 != Result )\r
+                       TRACE(_T("Bind failed\n"));\r
+               return Result;\r
+       }\r
+\r
+       inline int CSocket::Connect(LPCTSTR addr, LPCTSTR port)\r
+       // The Connect function establishes a connection to the socket.\r
+       {\r
+               int RetVal = 0;\r
+\r
+               if (IsIPV6Supported())\r
+               {\r
+\r
+#ifdef GetAddrInfo     // Skip the following code block for older development environments\r
+\r
+                       ADDRINFO Hints= {0};\r
+                       Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;\r
+                       ADDRINFO *AddrInfo;\r
+\r
+                       RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);\r
+                       if (RetVal != 0)\r
+                       {\r
+                               TRACE( _T("getaddrinfo failed\n"));\r
+                               return SOCKET_ERROR;\r
+                       }\r
+\r
+                       // Bind the IP address to the listening socket\r
+                       RetVal = Connect( AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );\r
+                       if ( RetVal == SOCKET_ERROR )\r
+                       {\r
+                               TRACE(_T("Connect failed\n"));\r
+                               return RetVal;\r
+                       }\r
+\r
+                       // Free the address information allocatied by GetAddrInfo\r
+                       FreeAddrInfo(AddrInfo);\r
+\r
+#endif\r
+\r
+               }\r
+               else\r
+               {\r
+                       sockaddr_in clientService;\r
+                       clientService.sin_family = AF_INET;\r
+                       clientService.sin_addr.s_addr = inet_addr( T2A(addr) );\r
+                       int nPort = -1;\r
+                       nPort = atoi( T2A(port) );\r
+                       if (-1 == nPort)\r
+                       {\r
+                               TRACE(_T("Invalid port number\n"));\r
+                               return SOCKET_ERROR;\r
+                       }\r
+                       clientService.sin_port = htons( (u_short)nPort );\r
+\r
+                       RetVal = ::connect( m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) );\r
+                       if ( 0 != RetVal )\r
+                               TRACE(_T("Connect failed\n"));\r
+               }\r
+\r
+               return RetVal;\r
+       }\r
+\r
+       inline int CSocket::Connect(const struct sockaddr* name, int namelen)\r
+       {\r
+               // The Connect function establishes a connection to the socket.\r
+\r
+               int Result = ::connect( m_Socket, name, namelen );\r
+               if ( 0 != Result )\r
+                       TRACE(_T("Connect failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline bool CSocket::Create( int family, int type, int protocol /*= IPPROTO_IP*/)\r
+       {\r
+               // Creates the socket\r
+\r
+               // Valid values:\r
+               //  family:             AF_INET or AF_INET6\r
+               //      type:           SOCK_DGRAM, SOCK_SEQPACKET, SOCK_STREAM, SOCK_RAW\r
+               //      protocol:       IPPROTO_IP, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_RAW, IPPROTO_ICMP, IPPROTO_ICMPV6\r
+\r
+               m_Socket = socket(family, type, protocol);\r
+               if(m_Socket == INVALID_SOCKET)\r
+               {\r
+                       TRACE(_T("Failed to create socket\n"));\r
+                       return FALSE;\r
+               }\r
+\r
+               return TRUE;\r
+       }\r
+\r
+       inline void CSocket::Disconnect()\r
+       {\r
+               ::shutdown(m_Socket, SD_BOTH);\r
+               StopEvents();\r
+               ::closesocket(m_Socket);\r
+               m_Socket = INVALID_SOCKET;\r
+       }\r
+\r
+       inline UINT WINAPI CSocket::EventThread(LPVOID thread_data)\r
+       {\r
+               // These are the possible network event notifications:\r
+               //      FD_READ         Notification of readiness for reading.\r
+               //      FD_WRITE        Motification of readiness for writing.\r
+               //      FD_OOB          Notification of the arrival of Out Of Band data.\r
+               //      FD_ACCEPT       Notification of incoming connections.\r
+               //      FD_CONNECT      Notification of completed connection or multipoint join operation.\r
+               //      FD_CLOSE        Notification of socket closure.\r
+               //      FD_QOS          Notification of socket Quality Of Service changes\r
+               //      FD_ROUTING_INTERFACE_CHANGE     Notification of routing interface changes for the specified destination.\r
+               //      FD_ADDRESS_LIST_CHANGE          Notification of local address list changes for the address family of the socket.\r
+\r
+               WSANETWORKEVENTS NetworkEvents;\r
+               CSocket* pSocket = (CSocket*)thread_data;\r
+               SOCKET sClient = pSocket->m_Socket;\r
+\r
+        WSAEVENT AllEvents[2];\r
+               AllEvents[0] = ::WSACreateEvent();\r
+               AllEvents[1] = (WSAEVENT)pSocket->m_StopRequest;\r
+               long Events = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE |\r
+                                 FD_QOS | FD_ROUTING_INTERFACE_CHANGE | FD_ADDRESS_LIST_CHANGE;\r
+\r
+               // Associate the network event object (hNetworkEvents) with the\r
+               // specified network events (Events) on socket sClient.\r
+               if(     SOCKET_ERROR == WSAEventSelect(sClient, AllEvents[0], Events))\r
+               {\r
+                       TRACE(_T("Error in Event Select\n"));\r
+                       ::SetEvent(pSocket->m_Stopped);\r
+                       ::WSACloseEvent(AllEvents[0]);\r
+                       return 0;\r
+               }\r
+\r
+               // loop until the stop event is set\r
+               for (;;) // infinite loop\r
+               {\r
+                       // Wait 100 ms for a network event\r
+                       DWORD dwResult = ::WSAWaitForMultipleEvents(2, AllEvents, FALSE, THREAD_TIMEOUT, FALSE);\r
+\r
+                       // Check event for stop thread\r
+                       if(::WaitForSingleObject(pSocket->m_StopRequest, 0) == WAIT_OBJECT_0)\r
+                       {\r
+                               ::WSACloseEvent(AllEvents[0]);\r
+                               ::SetEvent(pSocket->m_Stopped);\r
+                               return 0;\r
+                       }\r
+\r
+                       if (WSA_WAIT_FAILED == dwResult)\r
+                       {\r
+                               TRACE(_T("WSAWaitForMultipleEvents failed\n"));\r
+                               ::WSACloseEvent(AllEvents[0]);\r
+                               ::SetEvent(pSocket->m_Stopped);\r
+                               return 0;\r
+                       }\r
+\r
+                       // Proceed if a network event occurred\r
+                       if (WSA_WAIT_TIMEOUT != dwResult)\r
+                       {\r
+\r
+                               if ( SOCKET_ERROR == ::WSAEnumNetworkEvents(sClient, AllEvents[0], &NetworkEvents) )\r
+                               {\r
+                                       TRACE(_T("WSAEnumNetworkEvents failed\n"));\r
+                                       ::WSACloseEvent(AllEvents[0]);\r
+                                       ::SetEvent(pSocket->m_Stopped);\r
+                                       return 0;\r
+                               }\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_ACCEPT)\r
+                                       pSocket->OnAccept();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_READ)\r
+                                       pSocket->OnReceive();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_WRITE)\r
+                                       pSocket->OnSend();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_OOB)\r
+                                       pSocket->OnOutOfBand();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_QOS)\r
+                                       pSocket->OnQualityOfService();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_CONNECT)\r
+                                       pSocket->OnConnect();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE)\r
+                                       pSocket->OnRoutingChange();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_ADDRESS_LIST_CHANGE)\r
+                                       pSocket->OnAddresListChange();\r
+\r
+                               if (NetworkEvents.lNetworkEvents & FD_CLOSE)\r
+                               {\r
+                                       ::shutdown(sClient, SD_BOTH);\r
+                                       ::closesocket(sClient);\r
+                                       pSocket->OnDisconnect();\r
+                                       ::WSACloseEvent(AllEvents[0]);\r
+                                       ::SetEvent(pSocket->m_Stopped);\r
+                                       return 0;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       inline int CSocket::GetAddrInfo( LPCTSTR nodename, LPCTSTR servname, const struct addrinfo* hints, struct addrinfo** res)\r
+       {\r
+\r
+#ifdef GetAddrInfo\r
+\r
+               std::string sNodeName = T2A(nodename);\r
+               std::string sServName = T2A(servname);\r
+               return (*m_pfnGetAddrInfo)(sNodeName.c_str(), sServName.c_str(), hints, res);\r
+\r
+#else\r
+\r
+               UNREFERENCED_PARAMETER(nodename);\r
+               UNREFERENCED_PARAMETER(servname);\r
+               UNREFERENCED_PARAMETER(hints);\r
+               UNREFERENCED_PARAMETER(res);\r
+\r
+               throw CWinException(_T("getaddrinfo is not supported"));\r
+\r
+#endif\r
+\r
+       }\r
+\r
+       inline LPCTSTR CSocket::GetLastError()\r
+       {\r
+               // Retrieves the most recent network error.\r
+\r
+               int ErrorCode = WSAGetLastError();\r
+               LPTSTR Message = NULL;\r
+               m_ErrorMessage = _T("");\r
+\r
+               FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |\r
+                                         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,\r
+                                         NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
+                                         (LPTSTR)&Message, 1024, NULL);\r
+\r
+               if (Message)\r
+               {\r
+                       m_ErrorMessage = Message;\r
+                       ::LocalFree(Message);\r
+               }\r
+\r
+               return m_ErrorMessage;\r
+       }\r
+\r
+       inline int  CSocket::GetPeerName(struct sockaddr* name, int* namelen)\r
+       {\r
+               int Result = ::getpeername(m_Socket, name, namelen);\r
+               if (0 != Result)\r
+                       TRACE(_T("GetPeerName failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int  CSocket::GetSockName(struct sockaddr* name, int* namelen)\r
+       {\r
+               int Result = ::getsockname(m_Socket, name, namelen);\r
+               if (0 != Result)\r
+                       TRACE(_T("GetSockName Failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int  CSocket::GetSockOpt(int level, int optname, char* optval, int* optlen)\r
+       {\r
+               int Result = ::getsockopt(m_Socket, level, optname, optval, optlen);\r
+               if (0 != Result)\r
+                       TRACE(_T("GetSockOpt Failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline void CSocket::FreeAddrInfo( struct addrinfo* ai )\r
+       {\r
+\r
+#ifdef GetAddrInfo\r
+\r
+               (*m_pfnFreeAddrInfo)(ai);\r
+\r
+#else\r
+\r
+               UNREFERENCED_PARAMETER(ai);\r
+\r
+               throw CWinException(_T("getaddrinfo is not supported"));\r
+\r
+#endif\r
+\r
+       }\r
+\r
+       inline int CSocket::ioCtlSocket(long cmd, u_long* argp)\r
+       {\r
+               int Result = ::ioctlsocket(m_Socket, cmd, argp);\r
+               if (0 != Result)\r
+                       TRACE(_T("ioCtlSocket Failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline bool CSocket::IsIPV6Supported()\r
+       {\r
+               bool IsIPV6Supported = FALSE;\r
+\r
+#ifdef GetAddrInfo\r
+\r
+               if (m_pfnGetAddrInfo != 0 && m_pfnFreeAddrInfo != 0)\r
+                       IsIPV6Supported = TRUE;\r
+\r
+#endif\r
+\r
+               return IsIPV6Supported;\r
+       }\r
+\r
+       inline int CSocket::Listen(int backlog /*= SOMAXCONN*/)\r
+       {\r
+               int Result = ::listen(m_Socket, backlog);\r
+               if (0 != Result)\r
+                       TRACE(_T("Listen Failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int CSocket::Receive(TCHAR* buf, int len, int flags)\r
+       {\r
+               std::vector<char> vChar(len+1, '\0');\r
+               char* pCharArray = &vChar.front();\r
+               int Result = ::recv(m_Socket, pCharArray, len, flags);\r
+               if (SOCKET_ERROR == Result)\r
+                       TRACE(_T("Receive failed\n"));\r
+\r
+               lstrcpyn(buf, A2T(pCharArray), len);\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int CSocket::ReceiveFrom(TCHAR* buf, int len, int flags, struct sockaddr* from, int* fromlen)\r
+       //The ReceiveFrom function receives a datagram and stores the source address.\r
+       {\r
+               std::vector<char> vChar(len+1, '\0');\r
+               char* pCharArray = &vChar.front();\r
+               int Result = ::recvfrom(m_Socket, pCharArray, len, flags, from, fromlen);\r
+               if (SOCKET_ERROR == Result)\r
+                       TRACE(_T("ReceiveFrom failed\n"));\r
+\r
+               lstrcpyn(buf, A2T(pCharArray), len);\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int CSocket::Send(LPCTSTR buf, int len, int flags)\r
+       {\r
+               int Result = ::send(m_Socket, T2A(buf), len, flags);\r
+               if (SOCKET_ERROR == Result)\r
+                       TRACE(_T("Send failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int CSocket::SendTo(LPCTSTR send, int len, int flags, LPCTSTR addr, LPCTSTR port)\r
+       // The sendto function sends data to a specific destination.\r
+       {\r
+               int RetVal = 0;\r
+\r
+               if (IsIPV6Supported())\r
+               {\r
+\r
+#ifdef GetAddrInfo     // Skip the following code block for older development environments\r
+\r
+                       ADDRINFO Hints= {0};\r
+                       Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;\r
+                       ADDRINFO *AddrInfo;\r
+\r
+                       RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);\r
+                       if (RetVal != 0)\r
+                       {\r
+                               TRACE( _T("GetAddrInfo failed\n"));\r
+                               return SOCKET_ERROR;\r
+                       }\r
+\r
+                       RetVal = ::sendto(m_Socket, T2A(send), len, flags, AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );\r
+                       if ( RetVal == SOCKET_ERROR )\r
+                       {\r
+                               TRACE(_T("SendTo failed\n"));\r
+                               return RetVal;\r
+                       }\r
+\r
+                       // Free the address information allocatied by GetAddrInfo\r
+                       FreeAddrInfo(AddrInfo);\r
+\r
+#endif\r
+\r
+               }\r
+               else\r
+               {\r
+                       sockaddr_in clientService;\r
+                       clientService.sin_family = AF_INET;\r
+                       clientService.sin_addr.s_addr = inet_addr( T2A(addr) );\r
+                       int nPort = -1;\r
+            nPort = atoi( T2A(port));\r
+                       if (-1 == nPort)\r
+                       {\r
+                               TRACE(_T("Invalid port number\n"));\r
+                               return SOCKET_ERROR;\r
+                       }\r
+                       clientService.sin_port = htons( (u_short)nPort );\r
+\r
+                       RetVal = ::sendto( m_Socket, T2A(send), len, flags, (SOCKADDR*) &clientService, sizeof(clientService) );\r
+                       if ( SOCKET_ERROR != RetVal )\r
+                               TRACE(_T("SendTo failed\n"));\r
+               }\r
+\r
+               return RetVal;\r
+       }\r
+\r
+       inline int CSocket::SendTo(LPCTSTR buf, int len, int flags, const struct sockaddr* to, int tolen)\r
+       // The sendto function sends data to a specific destination.\r
+       {\r
+               int Result =  ::sendto(m_Socket, T2A(buf), len, flags, to, tolen);\r
+               if (SOCKET_ERROR == Result)\r
+                       TRACE(_T("SendTo failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline int CSocket::SetSockOpt(int level, int optname, const char* optval, int optlen)\r
+       {\r
+               int Result = ::setsockopt(m_Socket, level, optname, optval, optlen);\r
+               if (0 != Result)\r
+                       TRACE(_T("SetSockOpt failed\n"));\r
+\r
+               return Result;\r
+       }\r
+\r
+       inline void CSocket::StartEvents()\r
+       {\r
+               // This function starts the thread which monitors the socket for events.\r
+               StopEvents();   // Ensure the thread isn't already running\r
+               UINT ThreadID;  // a return variable required for Win95, Win98, WinME\r
+               m_hEventThread = (HANDLE)::_beginthreadex(NULL, 0, CSocket::EventThread, (LPVOID) this, 0, &ThreadID);\r
+       }\r
+\r
+       inline void CSocket::StopEvents()\r
+       {\r
+               // Terminates the event thread gracefully (if possible)\r
+               if (m_hEventThread)\r
+               {\r
+                       ::SetThreadPriority(m_hEventThread, THREAD_PRIORITY_HIGHEST);\r
+                       ::SetEvent(m_StopRequest);\r
+\r
+                       for (;;)        // infinite loop\r
+                       {\r
+                               // wait for the Thread stopping event to be set\r
+                               if ( WAIT_TIMEOUT == ::WaitForSingleObject(m_Stopped, THREAD_TIMEOUT * 10) )\r
+                               {\r
+                                       // Note: An excessive delay in processing any of the notification functions\r
+                                       // can cause us to get here. (Yes one second is an excessive delay. Its a bug!)\r
+                                       TRACE(_T("*** Error: Event Thread won't die ***\n") );\r
+                               }\r
+                               else break;\r
+                       }\r
+\r
+                       ::CloseHandle(m_hEventThread);\r
+                       m_hEventThread = 0;\r
+               }\r
+\r
+               ::ResetEvent(m_StopRequest);\r
+               ::ResetEvent(m_Stopped);\r
+       }\r
+}\r
+\r
+\r
+#endif // #ifndef _WIN32XX_SOCKET_H_\r
+\r

UCC git Repository :: git.ucc.asn.au