#include "stdafx.h" #ifdef WIN32 #include <stdlib.h> #ifndef UNDER_CE #include <crtdbg.h> #endif #include <strsafe.h> #endif #include "SocketHandle.h" // Jeff.add. //#include "Wspiapi.h" //#include "Ws2tcpip.h" #include <MSTcpIP.h> #ifndef BUFFER_SIZE #define BUFFER_SIZE 64*1024 #endif #ifndef SOCKHANDLE_TTL #define SOCKHANDLE_TTL 5 #endif #ifndef SOCKHANDLE_HOPS #define SOCKHANDLE_HOPS 10 #endif #define HOSTNAME_SIZE MAX_PATH #define STRING_LENGTH 40 #if !defined(PLATFORM_HAS_INETFUNC) const char *_inet_ntop(int af, const void *src, char *dst, size_t cnt); int _inet_pton(int af, const char *src, void *dst); #endif #ifdef WIN32 #ifndef UNDER_CE #pragma comment(lib, "ws2_32.lib") #else #pragma comment(lib, "Ws2.lib") #endif #endif #if 1 typedef struct STcpKeepAlive2 { DWORD onoff; DWORD keepalivetime; DWORD keepaliveinterval; }TCP_KEEP_ALIVE2; /************************************************************************/ /* ������SetKeepLive[2/29/2016 IT]; /* ����������TCP�����ʻ�ʱ��; /* ������; /* [IN] Socket��Ҫ���õĿͻ���SOCKET; /* ���أ����óɹ�����TRUE; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ BOOL SetKeepLive(IN SOCKET &Socket) { const BYTE chOpt = 1; // True; // Set KeepAlive �����������, ��ֹ����˲���������; if (setsockopt(Socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&chOpt, sizeof(chOpt)) == SOCKET_ERROR) { printf("���ÿͻ����ʻ����ʧ��1\n\n"); return FALSE; } // ���ó�ʱ��ϸ��Ϣ; BYTE byRet[5] = {0}; TCP_KEEP_ALIVE2 klive; klive.onoff = 1; // ���ñ���; klive.keepalivetime = 1000 * 15; // 3���ӳ�ʱ Keep Alive; klive.keepaliveinterval = 1000 * 5; // ���Լ��Ϊ5�� Resend if No-Reply; INT nResult = WSAIoctl ( Socket, SIO_KEEPALIVE_VALS, &klive, sizeof(TCP_KEEP_ALIVE2), NULL, 0, (unsigned long *)&byRet, 0, NULL ); if ( nResult == SOCKET_ERROR ) { printf("���ÿͻ����ʻ����ʧ��2\n\n"); return FALSE; } return TRUE; } #endif CSocketHandle::CSocketHandle(): m_hSocket(INVALID_SOCKET) { m_npendingSize = 0; memset(m_szpendingbuf,0,SOCKET_BUFFSIZE); } CSocketHandle::~CSocketHandle() { Close(); } bool CSocketHandle::IsOpen() const { return ( INVALID_SOCKET != m_hSocket ); } SOCKET CSocketHandle::GetSocket() const { return m_hSocket; } /************************************************************************/ /* ������GetSocketType[2/29/2016 IT]; /* ��������ȡ��������; /* ������; /* ���أ�����-1��ʾ����һ����Ч������; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ int CSocketHandle::GetSocketType() const { int type = -1; if ( INVALID_SOCKET != m_hSocket ) { socklen_t optlen = sizeof(int); if ( getsockopt(GetSocket(), SOL_SOCKET, SO_TYPE, reinterpret_cast<char*>(&type),&optlen) == SOCKET_ERROR) { SetLastError( WSAGetLastError() ); } } return type; } /************************************************************************/ /* ������Attach[2/29/2016 IT]; /* ����������һ��SOCKET���,ʹ��Detach������Close�������ͷž��; /* ������; /* [IN] sock��Ҫ���ӵ����е����־��; /* ���أ��ɹ�����TRUE; /* ע�⣺�����п���ʧ��,��Ҫ���ӵ�������һ����Чֵ���ֵ����ʹ��ʱ; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::Attach(IN SOCKET sock) { if ( INVALID_SOCKET == m_hSocket ) { m_hSocket = sock; return true; } return false; } /************************************************************************/ /* ������Detach[2/29/2016 IT]; /* �����������ִ�������з������; /* ��������; /* ���أ�����ǰ�渽�ӵ����־����INVALID_SOCKET; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ SOCKET CSocketHandle::Detach() { SOCKET sock = m_hSocket; ::InterlockedExchange(reinterpret_cast<long*>(&m_hSocket), INVALID_SOCKET); return sock; } /************************************************************************/ /* ������GetSockName[2/29/2016 IT]; /* ��������ȡ������(���ص�ַ); /* ������; /* [OUT] saddr_in�����ӳɹ�ʱ���صĵ�ǰ���ص�ַ�Ͷ˿ں�; /* ���أ��ɹ�����TRUE; /* ע�⣺ʹ��ǰ�������InitLibrary����; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::GetSockName(OUT SockAddrIn& saddr_in) const { _ASSERTE( IsOpen() ); if (IsOpen()) { socklen_t namelen = (socklen_t)saddr_in.Size(); if (SOCKET_ERROR != getsockname(GetSocket(), saddr_in, &namelen)) { return true; } SetLastError( WSAGetLastError() ); } return false; } /************************************************************************/ /* ������GetPeerName[2/29/2016 IT]; /* ��������ȡ��Ե���ӽ���(��ȡPeer��ַ);; /* ������; /* [OUT] saddr_in�� peer address and port (use only with TCP or client mode UDP); /* ���أ��ɹ�����TRUE; /* ע�⣺ʹ��ǰ�������InitLibrary����; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::GetPeerName(OUT SockAddrIn& saddr_in) const { _ASSERTE( IsOpen() ); if (IsOpen()) { socklen_t namelen = (socklen_t)saddr_in.Size(); if (SOCKET_ERROR != getpeername(GetSocket(), saddr_in, &namelen)) { return true; } SetLastError( WSAGetLastError() ); } return false; } /************************************************************************/ /* ������Close[2/29/2016 IT]; /* �������ر�����; /* ������; /* ���أ�void; /* ע�⣺��������InitLibrary, CreateSocket, ConnectTo, IsOpen; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ void CSocketHandle::Close() { if ( IsOpen() ) { ShutdownConnection(static_cast<SOCKET>(::InterlockedExchange((LONG*)&m_hSocket, INVALID_SOCKET))); } } /************************************************************************/ /* ������AddMembership[2/29/2016 IT]; /* ���������Ӷಥ��ַ; /* ������; /* [IN] pszIPAddr���ಥIP��; /* [IN] pszNIC��IP��ַ�ӿڣ���������ʱ��ijһ�������кţ�; /* ���أ��ɹ�����TRUE; /* ע�⣺����InitLibrary����; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::AddMembership(IN LPCTSTR pszIPAddr, IN LPCTSTR pszNIC) { _ASSERTE( IsOpen() ); if ( IsOpen() ) { int nType = 0; socklen_t nOptLen = sizeof(int); if ( SOCKET_ERROR != getsockopt(m_hSocket, SOL_SOCKET, SO_TYPE, (char*)&nType, &nOptLen)) { if ( nType == SOCK_DGRAM ) { // Setup interface for multicast traffic SockAddrIn mcastAddr; if (GetAddressInfo(pszIPAddr, NULL, AF_UNSPEC, mcastAddr)) { SockAddrIn interfAddr; GetAddressInfo(pszNIC, NULL, mcastAddr.ss_family, interfAddr); if ( mcastAddr.ss_family == AF_INET ) { int nTTL = SOCKHANDLE_TTL; if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&nTTL, sizeof(nTTL))) { ULONG ulNIC = interfAddr.GetIPAddr(); if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_IF,(char *) &ulNIC, sizeof(ulNIC))) { ip_mreq mreq = { 0 }; mreq.imr_multiaddr.s_addr = mcastAddr.GetIPAddr(); mreq.imr_interface.s_addr = ulNIC; if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq))) { return true; } } } } else if ( mcastAddr.ss_family == AF_INET6 ) { int nTTL = SOCKHANDLE_HOPS; if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&nTTL, sizeof(nTTL))) { ipv6_mreq mreq6 = { 0 }; IN6_ADDR mcin6 = ((sockaddr_in6*)&mcastAddr)->sin6_addr; memcpy(&(mreq6.ipv6mr_multiaddr), &mcin6, sizeof(IN6_ADDR)); if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq6, sizeof(mreq6))) { return true; } } } else { // invalid socket option WSASetLastError(WSAENOPROTOOPT); } } } else { // invalid socket option WSASetLastError(WSAENOPROTOOPT); } } SetLastError( WSAGetLastError() ); } return false; } /************************************************************************/ /* ������DropMembership[2/29/2016 IT]; /* �������Ƴ��ಥ��ַ; /* ������; /* [IN] pszIPAddr���ಥIP��; /* [IN] pszNIC��IP��ַ�ӿڣ���������ʱ��ijһ�������кţ�; /* ���أ��ɹ�����TRUE; /* ע�⣺����InitLibrary����; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::DropMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC) { _ASSERTE( IsOpen() ); if ( IsOpen() ) { int nType = 0; socklen_t nOptLen = sizeof(int); if ( SOCKET_ERROR != getsockopt(m_hSocket, SOL_SOCKET, SO_TYPE, (char*)&nType, &nOptLen)) { if ( nType == SOCK_DGRAM ) { SockAddrIn mcastAddr; if (GetAddressInfo(pszIPAddr, NULL, AF_UNSPEC, mcastAddr)) { SockAddrIn interfAddr; GetAddressInfo(pszNIC, NULL, mcastAddr.ss_family, interfAddr); if ( mcastAddr.ss_family == AF_INET ) { ip_mreq mreq; mreq.imr_multiaddr.s_addr = mcastAddr.GetIPAddr(); mreq.imr_interface.s_addr = interfAddr.GetIPAddr();; if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq))) { return true; } } else if ( mcastAddr.ss_family == AF_INET6 ) { ipv6_mreq mreq6 = { 0 }; IN6_ADDR mcin6 = ((sockaddr_in6*)&mcastAddr)->sin6_addr; memcpy(&(mreq6.ipv6mr_multiaddr), &mcin6, sizeof(IN6_ADDR)); if ( SOCKET_ERROR != setsockopt(m_hSocket, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (const char*)&mreq6, sizeof(mreq6))) { return true; } } else { // invalid socket option WSASetLastError(WSAENOPROTOOPT); } } } else { // invalid socket option WSASetLastError(WSAENOPROTOOPT); } } SetLastError( WSAGetLastError() ); } return false; } /************************************************************************/ /* ������CreateSocket[2/29/2016 IT]; /* �������������������; /* ������; /* [IN] pszHostName����������������������ַ; /* [IN] pszServiceName���������������IP�˿ں�; /* [IN] nFamily��Ҫ�õĵ�ַЭ������ͣ�IPV4��IPV6��; /* [IN] nType��Ҫ�������������ͣ�SOCK_STREAM �� SOCK_DGRAM��; /* [IN] uOptions������ѡ��(SO_BROADCAST,SO_REUSEADDR) ; /* ���أ��ɹ�����TRUE; /* ע�⣺ʹ��WSAGetLastError()������ȡ���Ĵ���,��������InitLibrary, ConnectTo, IsOpen; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::CreateSocket(IN LPCTSTR pszHostName, IN LPCTSTR pszServiceName, IN int nFamily, IN int nType, IN UINT uOptions /* = 0 */) { // Socket is already opened if ( IsOpen() ) { SetLastError(ERROR_ACCESS_DENIED); return false; } // Create a Socket that is bound to a specific service provider // nFamily: (AF_INET, AF_INET6) // nType: (SOCK_STREAM, SOCK_DGRAM) #ifdef SOCKHANDLE_USE_OVERLAPPED SOCKET sock = WSASocket(nFamily, nType, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); #else SOCKET sock = socket(nFamily, nType, IPPROTO_IP); #endif if (INVALID_SOCKET != sock) { if (uOptions & SO_REUSEADDR) { // Inform Windows Sockets provider that a bind on a socket should not be disallowed // because the desired address is already in use by another socket BOOL optval = TRUE; if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof( BOOL ) ) ) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } } if (nType == SOCK_DGRAM) { if ((uOptions & SO_BROADCAST) && (nFamily == AF_INET)) { // Inform Windows Sockets provider that broadcast messages are allowed BOOL optval = TRUE; if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (char *) &optval, sizeof( BOOL ) ) ) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } } #ifdef SOCKHANDLE_CONFIGBUF // configure buffer size socklen_t rcvbuf = BUFFER_SIZE; if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbuf, sizeof( int ) ) ) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } #endif } // Associate a local address with the socket SockAddrIn sockAddr; sockAddr.CreateFrom(pszHostName, pszServiceName, nFamily); if ( SOCKET_ERROR == bind(sock, sockAddr, (int)sockAddr.Size())) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } // Listen to the socket, only valid for connection socket (TCP) if (SOCK_STREAM == nType) { if ( SOCKET_ERROR == listen(sock, SOMAXCONN)) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } } // Success, now we may save this socket m_hSocket = sock; } return (INVALID_SOCKET != sock); } /************************************************************************/ /* ������ConnectTo[2/29/2016 IT]; /* �������ͻ������ӷ����; /* ������; /* [IN] pszHostName��Hostname or NIC address; /* [IN] pszRemote��Remote network address; /* [IN] pszServiceName��Network service name or port number; /* [IN] nFamily��address family to use (AF_INET, AF_INET6); /* [IN] nType��type of socket to create (SOCK_STREAM, SOCK_DGRAM); /* ���أ�return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error); /* ע�⣺��������InitLibrary, CreateSocket, IsOpen; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::ConnectTo(IN LPCTSTR pszHostName, IN LPCTSTR pszRemote, IN LPCTSTR pszServiceName, IN int nFamily, IN int nType) { // Socket is already opened if ( IsOpen() ) { SetLastError(ERROR_ACCESS_DENIED); return false; } // Create a Socket that is bound to a specific service provider // nFamily: (AF_INET, AF_INET6) // nType: (SOCK_STREAM, SOCK_DGRAM) #ifdef SOCKHANDLE_USE_OVERLAPPED SOCKET sock = WSASocket(nFamily, nType, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); #else SOCKET sock = socket(nFamily, nType, IPPROTO_IP); #endif if (INVALID_SOCKET != sock) { // Associate a local address with the socket but let provider assign a port number SockAddrIn sockAddr; if (false == sockAddr.CreateFrom(pszHostName, TEXT("0"), nFamily)) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } if ( SOCKET_ERROR == bind(sock, sockAddr, (int)sockAddr.Size())) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } #ifdef SOCKHANDLE_CONFIGBUF if (nType == SOCK_DGRAM) { // configure buffer size socklen_t rcvbuf = BUFFER_SIZE; if ( SOCKET_ERROR == setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbuf, sizeof( int ) ) ) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } } #endif // Now get destination address & port sockAddr.CreateFrom( pszRemote, pszServiceName, nFamily ); // try to connect - if fail, server not ready if (SOCKET_ERROR == connect( sock, sockAddr, (int)sockAddr.Size())) { SetLastError( WSAGetLastError() ); closesocket( sock ); return false; } // Success, now we may save this socket m_hSocket = sock; } return (INVALID_SOCKET != sock); } /************************************************************************/ /* ������Read[2/29/2016 IT]; /* �������������ж�ȡ����; /* ������; /* [OUT] lpBuffer��Buffer to receive data; /* [IN] dwSize��Size of buffer in bytes; /* [IN] lpAddrIn��Peer address for UDP - this must be NULL for TCP; /* [IN] dwTimeout��Read timeout in milliseconds; /* ���أ�return number of bytes read or (-1L) if fail; /* ע�⣺��������InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, Write, WriteEx; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ DWORD CSocketHandle::Read(OUT LPBYTE lpBuffer, IN DWORD dwSize, IN LPSOCKADDR lpAddrIn /* = NULL */, IN DWORD dwTimeout /* = INFINITE */) { _ASSERTE( IsOpen() ); _ASSERTE( lpBuffer != NULL ); if (!IsOpen() || lpBuffer == NULL || dwSize < 1L) return (DWORD)-1L; fd_set fdRead = { 0 }; TIMEVAL stTime; TIMEVAL *pstTime = NULL; if ( INFINITE != dwTimeout ) { stTime.tv_sec = dwTimeout/1000; stTime.tv_usec = (dwTimeout%1000)*1000; pstTime = &stTime; } SOCKET s = GetSocket(); // Set Descriptor FD_SET( s, &fdRead ); // Select function set read timeout DWORD dwBytesRead = 0L; int res = 1; if ( pstTime != NULL ) res = select((int)s, &fdRead, NULL, NULL, pstTime ); if ( res > 0) { if (lpAddrIn) { // UDP socklen_t fromlen = sizeof(SOCKADDR_STORAGE); res = recvfrom(s, reinterpret_cast<LPSTR>(lpBuffer), dwSize, 0, lpAddrIn, &fromlen); } else { // TCP res = recv(s, reinterpret_cast<LPSTR>(lpBuffer), dwSize, 0); } if ( res == 0 ) { WSASetLastError(WSAECONNRESET); res = SOCKET_ERROR; } } if ( res == SOCKET_ERROR ) { SetLastError( WSAGetLastError() ); } dwBytesRead = (DWORD)((res >= 0)?(res) : (-1)); return dwBytesRead; } #ifdef WIN32 /************************************************************************/ /* ������ReadEx[2/29/2016 IT]; /* �����������ֶ�ȡ����,�첽ģʽ��asynchronous mode��; /* ������; /* [OUT] lpBuffer��Buffer to receive data; /* [IN] dwSize��Size of buffer in bytes; /* [IN] lpAddrIn��SockAddrIn for UDP - this must be NULL for TCP; /* [IN] lpOverlapped��Windows Overlapped structure (required); /* [IN] lpCompletionRoutine��Winsock Completion routine (required); /* ���أ�return number of bytes read, overlapped operation is pending or (-1L) if fail; /* ע�⣺�������� InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, Write, WriteEx, IOControl, GetTransferOverlappedResult; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ DWORD CSocketHandle::ReadEx(OUT LPBYTE lpBuffer, IN DWORD dwSize, IN LPSOCKADDR lpAddrIn, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSACOMPLETIONROUTINE lpCompletionRoutine) { _ASSERTE( IsOpen() ); _ASSERTE( lpBuffer != NULL ); if (!IsOpen() || lpBuffer == NULL || dwSize < 1L) return (DWORD)-1L; SOCKET s = GetSocket(); // Send message to peer WSABUF wsabuf; wsabuf.buf = (char FAR*)lpBuffer; wsabuf.len = dwSize; // Select function set read timeout DWORD dwBytesRead = 0L; DWORD dwFlags = 0L; int res = 0; if (lpAddrIn) { // UDP socklen_t fromlen = sizeof(SOCKADDR_STORAGE); res = WSARecvFrom( s, &wsabuf, 1, &dwBytesRead, &dwFlags, lpAddrIn, &fromlen, lpOverlapped, lpCompletionRoutine); } else { // TCP res = WSARecv( s, &wsabuf, 1, &dwBytesRead, &dwFlags, lpOverlapped, lpCompletionRoutine); } if ( res == SOCKET_ERROR ) { res = WSAGetLastError(); if ( res != WSA_IO_PENDING ) { dwBytesRead = (DWORD)-1L; SetLastError( res ); } } return dwBytesRead; } #endif /************************************************************************/ /* ������Write[2/29/2016 IT]; /* ��������Ŀ�����ַ�������; /* ������; /* [IN] lpBuffer��Buffer to send; /* [IN] dwCount��Number of bytes to send; /* [IN] lpAddrIn��Peer address for UDP - this must be NULL for TCP; /* [IN] dwTimeout��Write timeout in milliseconds; /* ���أ�return number of bytes sent or (-1L) if fail; /* ע�⣺��������InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, ReadEx, WriteEx; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ DWORD CSocketHandle::Write(IN const LPBYTE lpBuffer, IN DWORD dwCount, IN const LPSOCKADDR lpAddrIn /* = NULL */, IN DWORD dwTimeout /* = INFINITE */) { _ASSERTE( IsOpen() ); _ASSERTE( NULL != lpBuffer ); // validate params if (!IsOpen() || NULL == lpBuffer) return (DWORD)-1L; fd_set fdWrite = { 0 }; TIMEVAL stTime; TIMEVAL *pstTime = NULL; if ( INFINITE != dwTimeout ) { stTime.tv_sec = dwTimeout/1000; stTime.tv_usec = (dwTimeout%1000)*1000; pstTime = &stTime; } SOCKET s = GetSocket(); // Set Descriptor FD_SET( s, &fdWrite ); // Select function set write timeout DWORD dwBytesWritten = 0L; int res = 1; if ( pstTime != NULL ) { res = select((int)s, NULL, &fdWrite, NULL, pstTime ); } if ( res > 0) { // Send message to peer if (lpAddrIn) { // UDP res = sendto( s, reinterpret_cast<LPCSTR>(lpBuffer), dwCount, 0, lpAddrIn, sizeof(SOCKADDR_STORAGE)); } else { // TCP res = send( s, reinterpret_cast<LPCSTR>(lpBuffer), dwCount, 0); } } if ( res == SOCKET_ERROR ) { SetLastError( WSAGetLastError() ); } dwBytesWritten = (DWORD)((res >= 0)?(res) : (-1)); return dwBytesWritten; } #ifdef WIN32 /************************************************************************/ /* ������WriteEx[2/29/2016 IT]; /* ��������Ŀ�����ַ�������,�첽ģʽ(asynchronous mode); /* ������; /* [IN] lpBuffer��Buffer to send; /* [IN] dwCount��Number of bytes to send; /* [IN] lpAddrIn��SockAddrIn for UDP - this must be NULL for TCP; /* [IN] lpOverlapped��Windows Overlapped structure (required); /* [IN] lpCompletionRoutine��Winsock Completion routine (required); /* ���أ�return number of bytes read, overlapped operation is pending or (-1L) if fail; /* ע�⣺��������InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, ReadEx, Write, IOControl, GetTransferOverlappedResult; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ DWORD CSocketHandle::WriteEx(IN const LPBYTE lpBuffer, IN DWORD dwCount, IN const LPSOCKADDR lpAddrIn, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSACOMPLETIONROUTINE lpCompletionRoutine) { _ASSERTE( IsOpen() ); _ASSERTE( NULL != lpBuffer ); // validate params if (!IsOpen() || NULL == lpBuffer) return (DWORD)-1L; SOCKET s = GetSocket(); // Select function set write timeout DWORD dwBytesWritten = 0L; int res = 0; // Send message to peer WSABUF wsabuf; wsabuf.buf = (char FAR*) lpBuffer; wsabuf.len = dwCount; if (lpAddrIn) { // UDP res = WSASendTo( s, &wsabuf, 1, &dwBytesWritten, 0, lpAddrIn, sizeof(SOCKADDR_STORAGE), lpOverlapped, lpCompletionRoutine); } else // TCP res = WSASend( s, &wsabuf, 1, &dwBytesWritten, 0, lpOverlapped, lpCompletionRoutine); if ( res == SOCKET_ERROR ) { res = WSAGetLastError(); if ( res != WSA_IO_PENDING ) { dwBytesWritten = (DWORD)-1L; SetLastError( res ); } } return dwBytesWritten; } #endif #ifdef WIN32 /************************************************************************/ /* ������IOControl[2/29/2016 IT]; /* ������Control the mode of a socket (asynchronous mode); /* ������; /* [IN] dwIoCode��Control code of operation to perform; /* [IN] lpInBuffer��Pointer to the input buffer; /* [IN] cbInBuffer��Size of the input buffer, in bytes; /* [IN] lpOutBuffer��Pointer to the output buffer; /* [IN] cbOutBuffer��Size of the output buffer, in bytes; /* [IN] lpcbBytesReturned��Pointer to actual number of bytes of output; /* [IN] lpOverlapped��Winsock Overlapped structure; /* [IN] lpCompletionRoutine��Winsock Completion routine; /* ���أ�return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error); /* ע�⣺��������InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, WriteEx, GetTransferOverlappedResult; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::IOControl( IN DWORD dwIoCode, IN LPBYTE lpInBuffer, IN DWORD cbInBuffer, IN LPBYTE lpOutBuffer, IN DWORD cbOutBuffer, IN LPDWORD lpcbBytesReturned, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSACOMPLETIONROUTINE lpCompletionRoutine ) { _ASSERTE( IsOpen() ); // validate params if ( !IsOpen() ) { SetLastError(ERROR_INVALID_HANDLE); return false; } int res; SOCKET s = GetSocket(); res = WSAIoctl(s, dwIoCode, lpInBuffer, cbInBuffer, lpOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine); if ( res == SOCKET_ERROR ) { SetLastError( WSAGetLastError() ); } return ( res != SOCKET_ERROR ); } /************************************************************************/ /* ������GetTransferOverlappedResult[2/29/2016 IT]; /* ������Get Overlapped result (asynchronous mode); /* ������; /* [IN] lpOverlapped��Windows Overlapped structure (required); /* [IN] lpcbTransfer��Pointer to get number of bytes transferred; /* [IN] bWait��Force wait for overlapped operation to complete; /* [IN] lpdwFlags��Optional flags (see MSDN on WSARecv API); /* [OUT] ��; /* [IN/OUT] ��; /* ���أ��ɹ�����TRUE; /* ע�⣺��������InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, WriteEx, IOControl; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::GetTransferOverlappedResult(IN LPWSAOVERLAPPED lpOverlapped, IN LPDWORD lpcbTransfer, IN bool bWait /* = true */, IN LPDWORD lpdwFlags /* = 0 */) { _ASSERTE( IsOpen() ); _ASSERTE( NULL != lpOverlapped ); // validate params if (!IsOpen() || NULL == lpOverlapped) { SetLastError(ERROR_INVALID_HANDLE); return false; } SOCKET s = GetSocket(); DWORD dwFlags = 0; if ( lpdwFlags == NULL ) lpdwFlags = &dwFlags; BOOL bRet = WSAGetOverlappedResult( s, lpOverlapped, lpcbTransfer, bWait, lpdwFlags ); if ( !bRet ) { SetLastError( WSAGetLastError() ); } return (bRet != FALSE); } #endif /////////////////////////////////////////////////////////////////////////////// // Utility functions /************************************************************************/ /* ������InitLibrary[2/29/2016 IT]; /* ������Initialize Winsock library. This function calls WSAStartup; /* ������; /* [IN] wVersion��Winsock version use MAKEWORD macro if possible (e.g.: MAKEWORD(2,2)); /* ���أ�return true if successful; /* ע�⣺����ReleaseLibrary; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::InitLibrary(IN WORD wVersion) { #ifdef WIN32 WSADATA WSAData = { 0 }; return ( 0 == WSAStartup( wVersion, &WSAData ) ); #else return true; #endif } /************************************************************************/ /* ������ReleaseLibrary[2/29/2016 IT]; /* ������Release Winsock library; /* ������; /* ���أ�return true if successful; /* ע�⣺����InitLibrary; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::ReleaseLibrary() { #ifdef WIN32 return ( 0 == WSACleanup() ); #else return true; #endif } /************************************************************************/ /* ������WaitForConnection[2/29/2016 IT]; /* ������Wait for a new connection; /* ������; /* [IN] sock��A TCP socket handle. A new socket is return returned; /* ���أ�return A new socket when a new client connects; /* ע�⣺����GetSocket, CreateSocket; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ SOCKET CSocketHandle::WaitForConnection(IN SOCKET sock) { #if 0 return accept(sock, 0, 0); #else SOCKET ncs = accept(sock, 0, 0); SetKeepLive(ncs); return ncs; #endif } /************************************************************************/ /* ������ShutdownConnection[2/29/2016 IT]; /* ������Shutdown a connection; /* ������; /* [IN] sock��Socket to shutdown communication; /* ���أ�return true if successful; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::ShutdownConnection(IN SOCKET sock) { shutdown(sock, SD_BOTH); return ( 0 == closesocket( sock )); } static unsigned char chMinClassA_IP [] = { 1, 0, 0, 0 } ; static unsigned char chMinClassD_IP [] = { 224, 0, 0, 0 } ; static unsigned char chMaxClassD_IP [] = { 239, 255, 255, 255 } ; /************************************************************************/ /* ������IsUnicastIP[2/29/2016 IT]; /* ������Check if IP address is unicast (network order); /* ������; /* [IN] ulAddr��IP address (expected valid unicast address); /* ���أ�return true if successful; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::IsUnicastIP( ULONG ulAddr ) { return (((unsigned char *) & ulAddr) [0] >= chMinClassA_IP [0] && ((unsigned char *) & ulAddr) [0] < chMinClassD_IP [0]) ; } /************************************************************************/ /* ������IsMulticastIP[2/29/2016 IT]; /* ������Check if IP address is multicast (network order); /* ������; /* [IN] ulAddr��IP address (expected valid multicast address); /* ���أ�return true if successful; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::IsMulticastIP( ULONG ulAddr ) { return (((unsigned char *) & ulAddr) [0] >= chMinClassD_IP [0] && ((unsigned char *) & ulAddr) [0] <= chMaxClassD_IP [0]) ; } /************************************************************************/ /* ������FormatIP[2/29/2016 IT]; /* ������Format IP address to string; /* ������; /* [IN] pszIPAddr��Buffer to hold string; /* [IN] nSize��Size of buffer in characters; /* [IN] ulAddr��IP Address to format; /* [IN] bFmtHost��Specify if address (ulAddr) is in host (true) or network format (false); /* ���أ�return true if successful. Possible error could be INSUFFICIENT_BUFFER; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::FormatIP(LPTSTR pszIPAddr, UINT nSize, ULONG ulAddr, bool bFmtHost) { if ( pszIPAddr && nSize > 8) { if ( bFmtHost ) ulAddr = htonl( ulAddr ); // Create Address string return (SUCCEEDED(StringCchPrintf(pszIPAddr, nSize, TEXT("%u.%u.%u.%u"), (UINT)(((PBYTE) &ulAddr)[0]), (UINT)(((PBYTE) &ulAddr)[1]), (UINT)(((PBYTE) &ulAddr)[2]), (UINT)(((PBYTE) &ulAddr)[3])))); } SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } /************************************************************************/ /* ������FormatIP[2/29/2016 IT]; /* ������Format IP address to string; /* ������; /* [IN] pszIPAddr��Buffer to hold string; /* [IN] nSize��Size of buffer in characters; /* [IN] addrIn��IP Address to format; /* ���أ�return true if successful. Possible error could be INSUFFICIENT_BUFFER; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::FormatIP(LPTSTR pszIPAddr, UINT nSize, const SockAddrIn& addrIn) { if ( pszIPAddr && nSize > 8) { const void* addr; char szIPAddr[MAX_PATH] = { 0 }; if (addrIn.ss_family == AF_INET) { addr = &((const sockaddr_in*)&addrIn)->sin_addr; } else { addr = &((const sockaddr_in6*)&addrIn)->sin6_addr; } if (_inet_ntop(addrIn.ss_family, const_cast<void*>(addr), szIPAddr, MAX_PATH) != NULL) { #ifdef _UNICODE return (0 != MultiByteToWideChar(CP_UTF8, 0, szIPAddr, -1, pszIPAddr, nSize )); #else ::StringCbCopyA(pszIPAddr, nSize, szIPAddr); return true; #endif } } SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } /************************************************************************/ /* ������GetPortNumber[2/29/2016 IT]; /* ������Get service port number; /* ������; /* [IN] pszServiceName��Network service name (e.g.: "ftp", "telnet") or port number; /* ���أ�return port number; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ USHORT CSocketHandle::GetPortNumber( LPCTSTR pszServiceName ) { LPSERVENT lpservent; USHORT nPort = 0; if ( _istdigit( pszServiceName[0] ) ) { nPort = (USHORT) _ttoi( pszServiceName ); } else { #ifdef _UNICODE char pstrService[HOSTNAME_SIZE] = { 0 }; WideCharToMultiByte(CP_UTF8, 0, pszServiceName, -1, pstrService, sizeof(pstrService), NULL, NULL ); #else LPCTSTR pstrService = pszServiceName; #endif // Convert network byte order to host byte order if ( (lpservent = getservbyname( pstrService, NULL )) != NULL ) nPort = ntohs( lpservent->s_port ); } return nPort; } /************************************************************************/ /* ������GetIPAddress[2/29/2016 IT]; /* ������Get IP address of a host; /* ������; /* [IN] pszHostName��host name or IP address; /* ���أ�return Host IP address in host format; /* ע�⣺����GetAddressInfo; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ ULONG CSocketHandle::GetIPAddress( LPCTSTR pszHostName ) { LPHOSTENT lphostent; ULONG uAddr = INADDR_NONE; TCHAR szLocal[HOSTNAME_SIZE] = { 0 }; // if no name specified, get local if ( NULL == pszHostName || !pszHostName[0]) { GetLocalName(szLocal, HOSTNAME_SIZE); pszHostName = szLocal; } #ifdef _UNICODE char pstrHost[HOSTNAME_SIZE] = { 0 }; WideCharToMultiByte(CP_UTF8, 0, pszHostName, -1, pstrHost, sizeof(pstrHost), NULL, NULL ); #else LPCTSTR pstrHost = pszHostName; #endif // Check for an Internet Protocol dotted address string uAddr = inet_addr( pstrHost ); if ( (INADDR_NONE == uAddr) && (strcmp( pstrHost, "255.255.255.255" )) ) { // It's not an address, then try to resolve it as a hostname if ( (lphostent = gethostbyname( pstrHost )) != NULL ) uAddr = *((ULONG *) lphostent->h_addr_list[0]); } return ntohl( uAddr ); } /************************************************************************/ /* ������GetLocalName[2/29/2016 IT]; /* ������Get current localname for this machine; /* ������; /* [IN] pszName��Buffer to receive host name; /* [IN] nSize��Size of this buffer in character; /* ���أ�return true if successful; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::GetLocalName(LPTSTR pszName, UINT nSize) { if (pszName != NULL && nSize > 0) { char szHost[HOSTNAME_SIZE] = { 0 }; // get host name, if fail, SetLastError is set if (SOCKET_ERROR != gethostname(szHost, sizeof(szHost))) { struct hostent* hp; hp = gethostbyname(szHost); if (hp != NULL) { ::StringCbCopyA(szHost, HOSTNAME_SIZE, hp->h_name); } // check if user provide enough buffer size_t cbLength = 0; ::StringCbLengthA(szHost, HOSTNAME_SIZE, &cbLength); if ( cbLength > nSize ) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } // Unicode conversion #ifdef _UNICODE return (0 != MultiByteToWideChar(CP_UTF8, 0, szHost, -1, pszName, nSize )); #else ::StringCbCopyA(pszName, nSize, szHost); return true; #endif } else SetLastError( WSAGetLastError() ); } else SetLastError(ERROR_INVALID_PARAMETER); return false; } /************************************************************************/ /* ������GetLocalAddress[2/29/2016 IT]; /* ������Get current (default) IP address for this machine; /* ������; /* [IN] pszAddress��Buffer to receive IP address (IPv4, IPv6 format); /* [IN] nSize��Size of this buffer in character; /* [IN] nFamily��address family to use (AF_INET, AF_INET6); /* ���أ�return true if successful; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::GetLocalAddress(LPTSTR pszAddress, UINT nSize, int nFamily /*= AF_INET*/) { if (pszAddress != NULL && nSize > 0) { TCHAR szHost[HOSTNAME_SIZE] = { 0 }; // Get computer local address // get host name, if fail, SetLastError is set if (GetLocalName(szHost, HOSTNAME_SIZE)) { char szAddress[MAX_PATH] = { 0 }; #ifdef _UNICODE char pstrHost[HOSTNAME_SIZE] = { 0 }; WideCharToMultiByte(CP_UTF8, 0, szHost, -1, pstrHost, sizeof(pstrHost), NULL, NULL ); #else LPCTSTR pstrHost = szHost; #endif // get address info sockaddr_storage addr_store = { 0 }; addr_store.ss_family = static_cast<short>(nFamily); _inet_pton(nFamily, pstrHost, &addr_store); const void* addr; if (addr_store.ss_family == AF_INET) { addr = &((const sockaddr_in*)&addr_store)->sin_addr; } else { addr = &((const sockaddr_in6*)&addr_store)->sin6_addr; } if (_inet_ntop(addr_store.ss_family, const_cast<void*>(addr), szAddress, MAX_PATH) != NULL) { // Unicode conversion #ifdef _UNICODE return (0 != MultiByteToWideChar(CP_UTF8, 0, szAddress, -1, pszAddress, nSize )); #else ::StringCbCopyA(pszAddress, nSize, szAddress); return true; #endif } else SetLastError( WSAGetLastError() ); } } else SetLastError(ERROR_INVALID_PARAMETER); return false; } /************************************************************************/ /* ������GetAddressInfo[2/29/2016 IT]; /* ������Get IP address info of a host (Supports: IPv4 and IPv6); /* ������; /* [IN] pszHostName��host name or IP address; /* [IN] pszServiceName��pszServiceName Network service name (e.g.: "ftp", "telnet") or port number; /* [IN] nFamily��address family to use (AF_INET, AF_INET6); /* [IN] sockAddr��Socket address to fill in; /* ���أ�return true if successful; /* ע�⣺; /* ʾ����; /* /* �ģ�; /* ���ڣ�; /* ���ݣ�; /************************************************************************/ bool CSocketHandle::GetAddressInfo(LPCTSTR pszHostName, LPCTSTR pszServiceName,int nFamily, SockAddrIn& sockAddr) { const TCHAR szZERO[] = TEXT("0"); ADDRINFO aiHints; ADDRINFO *aiList = NULL; memset(&aiHints, 0, sizeof(aiHints)); aiHints.ai_flags = AI_ADDRCONFIG; // Jeff.��ʱ����; aiHints.ai_family = static_cast<short>(nFamily); TCHAR szLocal[HOSTNAME_SIZE] = { 0 }; // if no name specified, get local if ( NULL == pszHostName || !pszHostName[0]) { GetLocalName(szLocal, HOSTNAME_SIZE); pszHostName = szLocal; } if ( NULL == pszServiceName || !pszServiceName[0]) { pszServiceName = szZERO; } #ifdef _UNICODE char pstrHost[HOSTNAME_SIZE] = { 0 }; WideCharToMultiByte(CP_UTF8, 0, pszHostName, -1, pstrHost, sizeof(pstrHost), NULL, NULL ); char pstrService[HOSTNAME_SIZE] = { 0 }; WideCharToMultiByte(CP_UTF8, 0, pszServiceName, -1, pstrService, sizeof(pstrService), NULL, NULL ); #else LPCTSTR pstrHost = pszHostName; LPCTSTR pstrService = pszServiceName; #endif if ( SOCKET_ERROR != getaddrinfo(pstrHost, pstrService, &aiHints, &aiList) && ( aiList != 0 )) { ADDRINFO ai = { 0 }; ai.ai_addr = sockAddr; memcpy(ai.ai_addr, aiList->ai_addr, aiList->ai_addrlen); freeaddrinfo( aiList ); return true; } SetLastError( WSAGetLastError() ); return false; } /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// #if !defined(PLATFORM_HAS_INETFUNC) /////////////////////////////////////////////////////////////////////////////// // inet_ntop #if 0 const char *_inet_ntop(int af, const void *src, char *dst, size_t cnt) { if ( dst != NULL) { dst[0] = 0; if (af == AF_INET) { sockaddr_in in; memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; memcpy(&in.sin_addr, src, sizeof(in_addr)); getnameinfo((sockaddr *)&in, sizeof(sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST); return dst; } else if (af == AF_INET6) { sockaddr_in6 in; memset(&in, 0, sizeof(in)); in.sin6_family = AF_INET6; memcpy(&in.sin6_addr, src, sizeof(in6_addr)); getnameinfo((sockaddr *)&in, sizeof(sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST); return dst; } } WSASetLastError(WSA_INVALID_PARAMETER); return dst; } /////////////////////////////////////////////////////////////////////////////// // inet_pton int _inet_pton(int af, const char *src, void *dst) { int result = SOCKET_ERROR; addrinfo aiHints, *aiList = NULL; memset(&aiHints, 0, sizeof(aiHints)); aiHints.ai_family = af; if ( SOCKET_ERROR != getaddrinfo(src, NULL, &aiHints, &aiList) && (aiList != NULL)) { memcpy(dst, aiList->ai_addr, aiList->ai_addrlen); freeaddrinfo(aiList); result = 0; } return result; } #else ////////////////////////////////////////////////////////////////////////// static const char * inet_ntop_v4 (const void *src, char *dst, size_t size) { const char digits[] = "0123456789"; int i; struct in_addr *addr = (struct in_addr *)src; u_long a = ntohl(addr->s_addr); const char *orig_dst = dst; if (size < INET_ADDRSTRLEN) { errno = ENOSPC; return NULL; } for (i = 0; i < 4; ++i) { int n = (a >> (24 - i * 8)) & 0xFF; int non_zerop = 0; if (non_zerop || n / 100 > 0) { *dst++ = digits[n / 100]; n %= 100; non_zerop = 1; } if (non_zerop || n / 10 > 0) { *dst++ = digits[n / 10]; n %= 10; non_zerop = 1; } *dst++ = digits[n]; if (i != 3) *dst++ = '.'; } *dst++ = '\0'; return orig_dst; } #ifdef HAVE_IPV6 static const char * inet_ntop_v6 (const void *src, char *dst, size_t size) { const char xdigits[] = "0123456789abcdef"; int i; const struct in6_addr *addr = (struct in6_addr *)src; const u_char *ptr = addr->s6_addr; const char *orig_dst = dst; int compressed = 0; if (size < INET6_ADDRSTRLEN) { errno = ENOSPC; return NULL; } for (i = 0; i < 8; ++i) { int non_zerop = 0; if (compressed == 0 && ptr[0] == 0 && ptr[1] == 0 && i <= 5 && ptr[2] == 0 && ptr[3] == 0 && ptr[4] == 0 && ptr[5] == 0) { compressed = 1; if (i == 0) *dst++ = ':'; *dst++ = ':'; for (ptr += 6, i += 3; i < 8 && ptr[0] == 0 && ptr[1] == 0; ++i, ptr += 2); if (i >= 8) break; } if (non_zerop || (ptr[0] >> 4)) { *dst++ = xdigits[ptr[0] >> 4]; non_zerop = 1; } if (non_zerop || (ptr[0] & 0x0F)) { *dst++ = xdigits[ptr[0] & 0x0F]; non_zerop = 1; } if (non_zerop || (ptr[1] >> 4)) { *dst++ = xdigits[ptr[1] >> 4]; non_zerop = 1; } *dst++ = xdigits[ptr[1] & 0x0F]; if (i != 7) *dst++ = ':'; ptr += 2; } *dst++ = '\0'; return orig_dst; } #endif /* HAVE_IPV6 */ const char * _inet_ntop(int af, const void *src, char *dst, size_t size) { switch (af) { case AF_INET : return inet_ntop_v4 (src, dst, size); #ifdef HAVE_IPV6 case AF_INET6 : return inet_ntop_v6 (src, dst, size); #endif default : //errno = EAFNOSUPPORT; return NULL; } } int _inet_pton(int af, const char *csrc, void *dst) { char * src; if (csrc == NULL || (src = strdup(csrc)) == NULL) { _set_errno( ENOMEM ); return 0; } switch (af) { case AF_INET: { struct sockaddr_in si4; INT r; INT s = sizeof(si4); si4.sin_family = AF_INET; r = WSAStringToAddress(src, AF_INET, NULL, (LPSOCKADDR) &si4, &s); free(src); src = NULL; if (r == 0) { memcpy(dst, &si4.sin_addr, sizeof(si4.sin_addr)); return 1; } } break; case AF_INET6: { struct sockaddr_in6 si6; INT r; INT s = sizeof(si6); si6.sin6_family = AF_INET6; r = WSAStringToAddress(src, AF_INET6, NULL, (LPSOCKADDR) &si6, &s); free(src); src = NULL; if (r == 0) { memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr)); return 1; } } break; default: _set_errno( ENOSYS/*EAFNOSUPPORT*/ ); return -1; } /* the call failed */ { int le = WSAGetLastError(); if (le == WSAEINVAL) return 0; _set_errno(le); return -1; } } #endif #endif