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