| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sal.hxx" |
| |
| #include "system.h" |
| |
| #include <osl/socket.h> |
| #include <osl/diagnose.h> |
| #include <rtl/alloc.h> |
| |
| #include "sockimpl.h" |
| |
| extern "C" { |
| |
| /* defines for shutdown */ |
| #ifdef GCC |
| # define SD_RECEIVE 0 |
| # define SD_SEND 1 |
| # define SD_BOTH 2 |
| #endif |
| |
| /* |
| oslSocketAddr is a pointer to a Berkeley struct sockaddr. |
| I refrained from using sockaddr_in because of possible further |
| extensions of this socket-interface (IP-NG?). |
| The intention was to hide all Berkeley data-structures from |
| direct access past the osl-interface. |
| |
| The current implementation is internet (IP) centered. All |
| the constructor-functions (osl_create...) take parameters |
| that will probably make sense only in the IP-environment |
| (e.g. because of using the dotted-Addr-format). |
| |
| If the interface will be extended to host other protocol- |
| families, I expect no externally visible changes in the |
| existing functions. You'll probably need only new |
| constructor-functions who take the different Addr |
| formats into consideration (maybe a long dotted Addr |
| or whatever). |
| */ |
| |
| /* |
| _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr |
| are the same! I don't like it very much but see no other easy way to |
| conceal the struct sockaddr from the eyes of the user. |
| */ |
| |
| #define OSL_INVALID_SOCKET INVALID_SOCKET /* WIN32 */ |
| #define OSL_SOCKET_ERROR SOCKET_ERROR /* WIN32 */ |
| |
| /*****************************************************************************/ |
| /* enum oslAddrFamily */ |
| /*****************************************************************************/ |
| |
| /* map */ |
| static DWORD FamilyMap[]= { |
| AF_INET, /* osl_Socket_FamilyInet */ |
| AF_IPX, /* osl_Socket_FamilyIpx */ |
| 0 /* osl_Socket_FamilyInvalid */ |
| }; |
| |
| /* reverse map */ |
| static oslAddrFamily osl_AddrFamilyFromNative(DWORD nativeType) |
| { |
| oslAddrFamily i= (oslAddrFamily) 0; |
| while(i != osl_Socket_FamilyInvalid) |
| { |
| if(FamilyMap[i] == nativeType) |
| return i; |
| i = (oslAddrFamily) ( (int)i + 1); |
| } |
| return i; |
| } |
| |
| /* macros */ |
| #define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y) |
| #define FAMILY_TO_NATIVE(x) (short)FamilyMap[x] |
| |
| /*****************************************************************************/ |
| /* enum oslProtocol */ |
| /*****************************************************************************/ |
| |
| /* map */ |
| static DWORD ProtocolMap[]= { |
| 0, /* osl_Socket_FamilyInet */ |
| NSPROTO_IPX, /* osl_Socket_FamilyIpx */ |
| NSPROTO_SPX, /* osl_Socket_ProtocolSpx */ |
| NSPROTO_SPXII, /* osl_Socket_ProtocolSpx_ii */ |
| 0 /* osl_Socket_ProtocolInvalid */ |
| }; |
| |
| /* macros */ |
| #define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y) |
| #define PROTOCOL_TO_NATIVE(x) ProtocolMap[x] |
| |
| /*****************************************************************************/ |
| /* enum oslSocketType */ |
| /*****************************************************************************/ |
| |
| /* map */ |
| static DWORD TypeMap[]= { |
| SOCK_STREAM, /* osl_Socket_TypeStream */ |
| SOCK_DGRAM, /* osl_Socket_TypeDgram */ |
| SOCK_RAW, /* osl_Socket_TypeRaw */ |
| SOCK_RDM, /* osl_Socket_TypeRdm */ |
| SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */ |
| 0 /* osl_Socket_TypeInvalid */ |
| }; |
| |
| /* reverse map */ |
| static oslSocketType osl_SocketTypeFromNative(DWORD nativeType) |
| { |
| oslSocketType i= (oslSocketType)0; |
| while(i != osl_Socket_TypeInvalid) |
| { |
| if(TypeMap[i] == nativeType) |
| return i; |
| i = (oslSocketType)((int)i+1); |
| } |
| return i; |
| } |
| |
| /* macros */ |
| #define TYPE_TO_NATIVE(x) TypeMap[x] |
| #define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y) |
| |
| /*****************************************************************************/ |
| /* enum oslSocketOption */ |
| /*****************************************************************************/ |
| |
| /* map */ |
| static DWORD OptionMap[]= { |
| SO_DEBUG, /* osl_Socket_OptionDebug */ |
| SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */ |
| SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */ |
| SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */ |
| SO_DONTROUTE, /* osl_Socket_OptionDontRoute */ |
| SO_BROADCAST, /* osl_Socket_OptionBroadcast */ |
| SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */ |
| SO_LINGER, /* osl_Socket_OptionLinger */ |
| SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */ |
| SO_SNDBUF, /* osl_Socket_OptionSndBuf */ |
| SO_RCVBUF, /* osl_Socket_OptionRcvBuf */ |
| SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */ |
| SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */ |
| SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */ |
| SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */ |
| SO_ERROR, /* osl_Socket_OptionError */ |
| SO_TYPE, /* osl_Socket_OptionType */ |
| TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */ |
| 0 /* osl_Socket_OptionInvalid */ |
| }; |
| |
| /* macros */ |
| #define OPTION_TO_NATIVE(x) OptionMap[x] |
| #define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y) |
| |
| /*****************************************************************************/ |
| /* enum oslSocketOptionLevel */ |
| /*****************************************************************************/ |
| |
| static DWORD OptionLevelMap[]= { |
| SOL_SOCKET, /* osl_Socket_LevelSocket */ |
| IPPROTO_TCP, /* osl_Socket_LevelTcp */ |
| 0 /* osl_invalid_SocketLevel */ |
| }; |
| |
| /* macros */ |
| #define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x] |
| #define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y) |
| |
| /*****************************************************************************/ |
| /* enum oslSocketMsgFlag */ |
| /*****************************************************************************/ |
| |
| static DWORD SocketMsgFlagMap[]= { |
| 0, /* osl_Socket_MsgNormal */ |
| MSG_OOB, /* osl_Socket_MsgOOB */ |
| MSG_PEEK, /* osl_Socket_MsgPeek */ |
| MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */ |
| MSG_MAXIOVLEN /* osl_Socket_MsgMaxIOVLen */ |
| }; |
| |
| /* macros */ |
| #define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x] |
| #define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y) |
| |
| /*****************************************************************************/ |
| /* enum oslSocketDirection */ |
| /*****************************************************************************/ |
| |
| static DWORD SocketDirection[]= { |
| SD_RECEIVE, /* osl_Socket_DirRead */ |
| SD_SEND, /* osl_Socket_DirWrite */ |
| SD_BOTH /* osl_Socket_DirReadwrite */ |
| }; |
| |
| /* macros */ |
| #define DIRECTION_TO_NATIVE(x) SocketDirection[x] |
| #define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y) |
| |
| /*****************************************************************************/ |
| /* enum oslSocketError */ |
| /*****************************************************************************/ |
| |
| static int SocketError[]= { |
| |
| 0, /* no error */ |
| WSAENOTSOCK, /* Socket operation on non-socket */ |
| WSAEDESTADDRREQ, /* Destination address required */ |
| WSAEMSGSIZE, /* Message too long */ |
| WSAEPROTOTYPE, /* Protocol wrong type for socket */ |
| WSAENOPROTOOPT, /* Protocol not available */ |
| WSAEPROTONOSUPPORT, /* Protocol not supported */ |
| WSAESOCKTNOSUPPORT, /* Socket type not supported */ |
| WSAEOPNOTSUPP, /* Operation not supported on socket */ |
| WSAEPFNOSUPPORT, /* Protocol family not supported */ |
| WSAEAFNOSUPPORT, /* Address family not supported by */ |
| /* protocol family */ |
| WSAEADDRINUSE, /* Address already in use */ |
| WSAEADDRNOTAVAIL, /* Can't assign requested address */ |
| WSAENETDOWN, /* Network is down */ |
| WSAENETUNREACH, /* Network is unreachable */ |
| WSAENETRESET, /* Network dropped connection because */ |
| /* of reset */ |
| WSAECONNABORTED, /* Software caused connection abort */ |
| WSAECONNRESET, /* Connection reset by peer */ |
| WSAENOBUFS, /* No buffer space available */ |
| WSAEISCONN, /* Socket is already connected */ |
| WSAENOTCONN, /* Socket is not connected */ |
| WSAESHUTDOWN, /* Can't send after socket shutdown */ |
| WSAETOOMANYREFS, /* Too many references: can't splice */ |
| WSAETIMEDOUT, /* Connection timed out */ |
| WSAECONNREFUSED, /* Connection refused */ |
| WSAEHOSTDOWN, /* Host is down */ |
| WSAEHOSTUNREACH, /* No route to host */ |
| WSAEWOULDBLOCK, /* call would block on non-blocking socket */ |
| WSAEALREADY, /* operation already in progress */ |
| WSAEINPROGRESS /* operation now in progress */ |
| }; |
| |
| /* reverse map */ |
| static oslSocketError osl_SocketErrorFromNative(int nativeType) |
| { |
| oslSocketError i= (oslSocketError)0; |
| |
| while(i != osl_Socket_E_InvalidError) |
| { |
| if(SocketError[i] == nativeType) |
| return i; |
| |
| i = (oslSocketError)( (int) i + 1); |
| } |
| return i; |
| } |
| |
| /* macros */ |
| #define ERROR_TO_NATIVE(x) SocketError[x] |
| #define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y) |
| |
| /*****************************************************************************/ |
| /* oslSocketDialupImpl */ |
| /*****************************************************************************/ |
| static oslSocketDialupImpl *pDialupImpl = NULL; |
| |
| #if 0 /* INTERNAL DEBUG ONLY */ |
| BOOL WINAPI __osl_autodial_Impl (DWORD dwFlags, DWORD dwReserved) |
| { |
| return 0; |
| } |
| |
| BOOL WINAPI __osl_autodialHangup_Impl (DWORD dwReserved) |
| { |
| return 1; |
| } |
| |
| BOOL WINAPI __osl_getConnectedState_Impl (LPDWORD lpdwFlags, DWORD dwReserved) |
| { |
| if (lpdwFlags) |
| *lpdwFlags = 0; |
| return 0; |
| } |
| #endif /* INTERNAL DEBUG ONLY */ |
| |
| /* |
| * __osl_createSocketDialupImpl. |
| */ |
| static oslSocketDialupImpl* __osl_createSocketDialupImpl (void) |
| { |
| oslSocketDialupImpl *pImpl; |
| pImpl = (oslSocketDialupImpl*)rtl_allocateZeroMemory( sizeof (oslSocketDialupImpl)); |
| |
| InitializeCriticalSection (&pImpl->m_hMutex); |
| |
| return (pImpl); |
| } |
| |
| /* |
| * __osl_initSocketDialupImpl. |
| */ |
| static void __osl_initSocketDialupImpl (oslSocketDialupImpl *pImpl) |
| { |
| #ifdef SOCKET_USE_AUTODIAL |
| if (pImpl) |
| { |
| HINSTANCE hModule; |
| |
| EnterCriticalSection (&pImpl->m_hMutex); |
| |
| hModule = LoadLibrary (INTERNET_MODULE_NAME); |
| if (!(hModule <= (HINSTANCE)HINSTANCE_ERROR)) |
| { |
| pImpl->m_pfnAttemptConnect = (INTERNETATTEMPTCONNECT) |
| (GetProcAddress (hModule, "InternetAttemptConnect")); |
| pImpl->m_pfnAutodial = (INTERNETAUTODIAL) |
| (GetProcAddress (hModule, "InternetAutodial")); |
| pImpl->m_pfnAutodialHangup = (INTERNETAUTODIALHANGUP) |
| (GetProcAddress (hModule, "InternetAutodialHangup")); |
| pImpl->m_pfnGetConnectedState = (INTERNETGETCONNECTEDSTATE) |
| (GetProcAddress (hModule, "InternetGetConnectedState")); |
| pImpl->m_hModule = hModule; |
| } |
| |
| LeaveCriticalSection (&pImpl->m_hMutex); |
| } |
| #else |
| pImpl = pImpl; /* avoid warnings */ |
| #endif |
| } |
| |
| /* |
| * __osl_destroySocketDialupImpl. |
| */ |
| static void __osl_destroySocketDialupImpl (oslSocketDialupImpl *pImpl) |
| { |
| if (pImpl) |
| { |
| EnterCriticalSection (&pImpl->m_hMutex); |
| |
| if (pImpl->m_dwFlags & INTERNET_CONNECTION_HANGUP) |
| { |
| if (pImpl->m_pfnAutodialHangup) |
| { |
| (pImpl->m_pfnAutodialHangup)(0); |
| pImpl->m_dwFlags &= ~INTERNET_CONNECTION_HANGUP; |
| } |
| } |
| |
| if (pImpl->m_hModule) |
| FreeLibrary (pImpl->m_hModule); |
| |
| LeaveCriticalSection (&pImpl->m_hMutex); |
| DeleteCriticalSection (&pImpl->m_hMutex); |
| |
| rtl_freeMemory (pImpl); |
| } |
| } |
| |
| /* |
| * __osl_querySocketDialupImpl. |
| */ |
| static sal_Bool __osl_querySocketDialupImpl (void) |
| { |
| sal_Bool result; |
| |
| if (pDialupImpl == NULL) |
| { |
| pDialupImpl = __osl_createSocketDialupImpl(); |
| __osl_initSocketDialupImpl (pDialupImpl); |
| } |
| |
| EnterCriticalSection (&pDialupImpl->m_hMutex); |
| |
| result = sal_True; |
| if (pDialupImpl->m_pfnGetConnectedState) |
| { |
| DWORD dwFlags = 0; |
| |
| result = (sal_Bool)(pDialupImpl->m_pfnGetConnectedState)(&dwFlags, 0); |
| pDialupImpl->m_dwFlags |= dwFlags; |
| } |
| |
| LeaveCriticalSection (&pDialupImpl->m_hMutex); |
| return (result); |
| } |
| |
| /* |
| * __osl_attemptSocketDialupImpl. |
| */ |
| static sal_Bool __osl_attemptSocketDialupImpl (void) |
| { |
| sal_Bool result; |
| |
| if (pDialupImpl == NULL) |
| { |
| pDialupImpl = __osl_createSocketDialupImpl(); |
| __osl_initSocketDialupImpl (pDialupImpl); |
| } |
| |
| EnterCriticalSection (&pDialupImpl->m_hMutex); |
| |
| result = __osl_querySocketDialupImpl(); |
| if (!result) |
| { |
| result = sal_True; |
| if (pDialupImpl->m_pfnAutodial) |
| { |
| result = (sal_Bool)(pDialupImpl->m_pfnAutodial)(0, 0); |
| if (result) |
| pDialupImpl->m_dwFlags |= INTERNET_CONNECTION_HANGUP; |
| else |
| WSASetLastError (WSAENETDOWN); |
| } |
| } |
| |
| LeaveCriticalSection (&pDialupImpl->m_hMutex); |
| return (result); |
| } |
| |
| /*****************************************************************************/ |
| /* oslSocketImpl */ |
| /*****************************************************************************/ |
| static sal_uInt32 g_nSocketImpl = 0; |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| static sal_uInt32 g_nSocketAddr = 0; |
| struct LeakWarning |
| { |
| ~LeakWarning() |
| { |
| if( g_nSocketImpl ) |
| OSL_TRACE( "sal_socket: %d socket instances leak\n" , g_nSocketImpl ); |
| if( g_nSocketAddr ) |
| OSL_TRACE( "sal_socket: %d socket address instances leak\n" , g_nSocketAddr ); |
| } |
| }; |
| LeakWarning socketWarning; |
| #endif |
| |
| /* |
| * __osl_createSocketImpl. |
| */ |
| oslSocket __osl_createSocketImpl(SOCKET Socket) |
| { |
| oslSocket pSockImpl = (oslSocket) rtl_allocateZeroMemory( sizeof(struct oslSocketImpl)); |
| pSockImpl->m_Socket = Socket; |
| pSockImpl->m_nRefCount = 1; |
| |
| g_nSocketImpl++; |
| |
| return (pSockImpl); |
| } |
| |
| /* |
| * __osl_destroySocketImpl. |
| */ |
| void __osl_destroySocketImpl(oslSocketImpl *pImpl) |
| { |
| if (pImpl) |
| { |
| if (--g_nSocketImpl == 0) |
| { |
| __osl_destroySocketDialupImpl (pDialupImpl); |
| pDialupImpl = NULL; |
| } |
| rtl_freeMemory (pImpl); |
| } |
| } |
| /*****************************************************************************/ |
| static oslSocketAddr __osl_createSocketAddr( ) |
| { |
| oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl )); |
| pAddr->m_nRefCount = 1; |
| #if OSL_DEBUG_LEVEL > 1 |
| g_nSocketAddr ++; |
| #endif |
| return pAddr; |
| } |
| |
| static oslSocketAddr __osl_createSocketAddrWithFamily( |
| oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr ) |
| { |
| OSL_ASSERT( family == osl_Socket_FamilyInet ); |
| |
| oslSocketAddr pAddr = __osl_createSocketAddr(); |
| switch( family ) |
| { |
| case osl_Socket_FamilyInet: |
| { |
| struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr); |
| |
| pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet); |
| pInetAddr->sin_addr.s_addr = nAddr; |
| pInetAddr->sin_port = (sal_uInt16)(port&0xffff); |
| break; |
| } |
| default: |
| pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family); |
| } |
| return pAddr; |
| } |
| |
| static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr ) |
| { |
| oslSocketAddr pAddr = __osl_createSocketAddr(); |
| memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( sockaddr ) ); |
| return pAddr; |
| } |
| |
| static void __osl_destroySocketAddr( oslSocketAddr addr ) |
| { |
| #if OSL_DEBUG_LEVEL > 1 |
| g_nSocketAddr --; |
| #endif |
| rtl_freeMemory( addr ); |
| } |
| /*****************************************************************************/ |
| /* osl_createEmptySocketAddr */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family) |
| { |
| oslSocketAddr pAddr = 0; |
| |
| /* is it an internet-Addr? */ |
| if (Family == osl_Socket_FamilyInet) |
| { |
| pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) ); |
| } |
| else |
| { |
| pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 ); |
| } |
| |
| return pAddr; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_copySocketAddr */ |
| /*****************************************************************************/ |
| // @deprecated, to be removed |
| oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr) |
| { |
| oslSocketAddr pCopy = 0; |
| if (Addr) |
| { |
| pCopy = __osl_createSocketAddr(); |
| |
| if (pCopy) |
| memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr)); |
| } |
| return pCopy; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_isEqualSocketAddr */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_isEqualSocketAddr(oslSocketAddr Addr1, oslSocketAddr Addr2) |
| { |
| struct sockaddr* pAddr1= &(Addr1->m_sockaddr); |
| struct sockaddr* pAddr2= &(Addr2->m_sockaddr); |
| |
| OSL_ASSERT(pAddr1); |
| OSL_ASSERT(pAddr2); |
| |
| if (pAddr1->sa_family == pAddr2->sa_family) |
| { |
| switch (pAddr1->sa_family) |
| { |
| case AF_INET: |
| { |
| struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1; |
| struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2; |
| |
| if ((pInetAddr1->sin_family == pInetAddr2->sin_family) && |
| (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) && |
| (pInetAddr1->sin_port == pInetAddr2->sin_port)) |
| return (sal_True); |
| } |
| |
| default: |
| { |
| return (memcmp(pAddr1, Addr2, sizeof(struct sockaddr)) == 0); |
| } |
| } |
| } |
| |
| return (sal_False); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_createInetBroadcastAddr */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_createInetBroadcastAddr ( |
| rtl_uString *strDottedAddr, |
| sal_Int32 Port) |
| { |
| sal_uInt32 nAddr = OSL_INADDR_NONE; |
| |
| if (strDottedAddr && strDottedAddr->length) |
| { |
| /* Dotted host address for limited broadcast */ |
| rtl_String *pDottedAddr = NULL; |
| |
| rtl_uString2String ( |
| &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length, |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| |
| nAddr = inet_addr (pDottedAddr->buffer); |
| rtl_string_release (pDottedAddr); |
| } |
| |
| if (nAddr != OSL_INADDR_NONE) |
| { |
| /* Limited broadcast */ |
| nAddr = ntohl(nAddr); |
| if (IN_CLASSA(nAddr)) |
| { |
| nAddr &= IN_CLASSA_NET; |
| nAddr |= IN_CLASSA_HOST; |
| } |
| else if (IN_CLASSB(nAddr)) |
| { |
| nAddr &= IN_CLASSB_NET; |
| nAddr |= IN_CLASSB_HOST; |
| } |
| else if (IN_CLASSC(nAddr)) |
| { |
| nAddr &= IN_CLASSC_NET; |
| nAddr |= IN_CLASSC_HOST; |
| } |
| else |
| { |
| /* No broadcast in class D */ |
| return ((oslSocketAddr)NULL); |
| } |
| nAddr = htonl(nAddr); |
| } |
| |
| oslSocketAddr pAddr = |
| __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons( (sal_uInt16) Port), nAddr ); |
| return pAddr; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_createInetSocketAddr */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_createInetSocketAddr ( |
| rtl_uString *strDottedAddr, |
| sal_Int32 Port) |
| { |
| DWORD Addr; |
| rtl_String *pDottedAddr=NULL; |
| |
| rtl_uString2String( |
| &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length, |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| |
| Addr= inet_addr (pDottedAddr->buffer); |
| rtl_string_release (pDottedAddr); |
| |
| oslSocketAddr pAddr = 0; |
| if(Addr != -1) |
| { |
| pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons( (sal_uInt16)Port), Addr ); |
| } |
| return pAddr; |
| } |
| |
| oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq ) |
| { |
| OSL_ASSERT( pAddr ); |
| OSL_ASSERT( pByteSeq ); |
| |
| oslSocketResult res = osl_Socket_Error; |
| if( pAddr && pByteSeq ) |
| { |
| OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) ); |
| OSL_ASSERT( pByteSeq->nElements == 4 ); |
| struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr); |
| memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 ); |
| res = osl_Socket_Ok; |
| } |
| return res; |
| } |
| |
| /** Returns the addr field in the struct sockaddr. ppByteSeq is in network byteorder. *ppByteSeq may |
| either be 0 or contain a constructed sal_Sequence. |
| */ |
| oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq ) |
| { |
| OSL_ASSERT( pAddr ); |
| OSL_ASSERT( ppByteSeq ); |
| |
| oslSocketResult res = osl_Socket_Error; |
| if( pAddr && ppByteSeq ) |
| { |
| struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr); |
| rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4); |
| res = osl_Socket_Ok; |
| } |
| return res; |
| } |
| |
| /*****************************************************************************/ |
| /* oslHostAddr */ |
| /*****************************************************************************/ |
| struct oslHostAddrImpl { |
| rtl_uString *pHostName; |
| oslSocketAddr pSockAddr; |
| } ; |
| |
| static oslHostAddr __osl_hostentToHostAddr (const struct hostent *he) |
| { |
| oslHostAddr pAddr= NULL; |
| oslSocketAddr pSocketAddr = 0; |
| |
| rtl_uString *cn= NULL; |
| |
| if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL)) |
| return ((oslHostAddr)NULL); |
| |
| rtl_string2UString( |
| &cn, he->h_name, strlen(he->h_name), |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| OSL_ASSERT(cn != 0); |
| |
| pSocketAddr = __osl_createSocketAddr(); |
| |
| if (pSocketAddr == NULL) |
| { |
| rtl_uString_release(cn); |
| return ((oslHostAddr)NULL); |
| } |
| |
| pSocketAddr->m_sockaddr.sa_family = he->h_addrtype; |
| if (pSocketAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) |
| { |
| struct sockaddr_in *sin= (struct sockaddr_in *)&(pSocketAddr->m_sockaddr); |
| memcpy ( |
| &(sin->sin_addr.s_addr), |
| he->h_addr_list[0], |
| he->h_length); |
| } |
| else |
| { |
| /* unknown address family */ |
| /* future extensions for new families might be implemented here */ |
| |
| OSL_TRACE("_osl_hostentToHostAddr(): unknown address family.\n"); |
| OSL_ASSERT(sal_False); |
| |
| __osl_destroySocketAddr( pSocketAddr ); |
| rtl_uString_release(cn); |
| return ((oslHostAddr)NULL); |
| } |
| |
| pAddr= (oslHostAddr )rtl_allocateMemory (sizeof (struct oslHostAddrImpl)); |
| |
| if (pAddr == NULL) |
| { |
| __osl_destroySocketAddr( pSocketAddr ); |
| rtl_uString_release(cn); |
| return ((oslHostAddr)NULL); |
| } |
| |
| pAddr->pHostName= cn; |
| pAddr->pSockAddr= pSocketAddr; |
| |
| return pAddr; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_createHostAddr */ |
| /*****************************************************************************/ |
| oslHostAddr SAL_CALL osl_createHostAddr ( |
| rtl_uString *strHostname, |
| const oslSocketAddr pSocketAddr) |
| { |
| oslHostAddr pAddr; |
| rtl_uString *cn= NULL; |
| |
| if ((strHostname == NULL) || (strHostname->length == 0) || (pSocketAddr == NULL)) |
| return ((oslHostAddr)NULL); |
| |
| rtl_uString_newFromString( &cn, strHostname); |
| |
| if ( ! pSocketAddr ) |
| { |
| rtl_uString_release(cn); |
| return ((oslHostAddr)NULL); |
| } |
| |
| pAddr= (oslHostAddr)rtl_allocateMemory (sizeof (struct oslHostAddrImpl)); |
| |
| if (pAddr == NULL) |
| { |
| rtl_uString_release(cn); |
| return ((oslHostAddr)NULL); |
| } |
| |
| pAddr->pHostName= cn; |
| pAddr->pSockAddr= osl_copySocketAddr( pSocketAddr ); |
| |
| return ((oslHostAddr)pAddr); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_createHostAddrByName */ |
| /*****************************************************************************/ |
| oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *strHostname) |
| { |
| if ((strHostname == NULL) || (strHostname->length == 0)) |
| return ((oslHostAddr)NULL); |
| |
| if (__osl_attemptSocketDialupImpl()) |
| { |
| struct hostent *he; |
| rtl_String *Hostname= NULL; |
| |
| rtl_uString2String( |
| &Hostname, strHostname->buffer, strHostname->length, |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| |
| he= gethostbyname (Hostname->buffer); |
| |
| rtl_string_release (Hostname); |
| return __osl_hostentToHostAddr (he); |
| } |
| return ((oslHostAddr)NULL); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_createHostAddrByAddr */ |
| /*****************************************************************************/ |
| oslHostAddr SAL_CALL osl_createHostAddrByAddr(const oslSocketAddr pAddr) |
| { |
| if (pAddr == NULL) |
| return ((oslHostAddr)NULL); |
| |
| if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) |
| { |
| const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr); |
| |
| if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) |
| return ((oslHostAddr)NULL); |
| |
| if (__osl_attemptSocketDialupImpl()) |
| { |
| struct hostent *he; |
| he= gethostbyaddr ((const sal_Char *)&(sin->sin_addr), |
| sizeof (sin->sin_addr), |
| sin->sin_family); |
| return __osl_hostentToHostAddr (he); |
| } |
| } |
| |
| return ((oslHostAddr)NULL); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_copyHostAddr */ |
| /*****************************************************************************/ |
| oslHostAddr SAL_CALL osl_copyHostAddr(const oslHostAddr Addr) |
| { |
| oslHostAddr pAddr= (oslHostAddr)Addr; |
| |
| if (pAddr) |
| return osl_createHostAddr (pAddr->pHostName, pAddr->pSockAddr); |
| else |
| return ((oslHostAddr)NULL); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getHostnameOfHostAddr */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_getHostnameOfHostAddr( |
| const oslHostAddr pAddr, rtl_uString **strHostname) |
| { |
| if (pAddr) |
| rtl_uString_assign (strHostname, pAddr->pHostName); |
| else |
| rtl_uString_new (strHostname); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getSocketAddrOfHostAddr */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr(const oslHostAddr pAddr) |
| { |
| if (pAddr) |
| return (const oslSocketAddr)(pAddr->pSockAddr); |
| else |
| return NULL; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_destroyHostAddr */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_destroyHostAddr(oslHostAddr pAddr) |
| { |
| if (pAddr) |
| { |
| if (pAddr->pHostName) |
| rtl_uString_release (pAddr->pHostName); |
| if (pAddr->pSockAddr) |
| osl_destroySocketAddr( pAddr->pSockAddr ); |
| |
| rtl_freeMemory (pAddr); |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getLocalHostname */ |
| /*****************************************************************************/ |
| oslSocketResult SAL_CALL osl_getLocalHostname (rtl_uString **strLocalHostname) |
| { |
| static sal_Unicode LocalHostname[256] = {0}; |
| |
| if (rtl_ustr_getLength(LocalHostname) == 0) |
| { |
| sal_Char Host[256]= ""; |
| if (gethostname(Host, sizeof(Host)) == 0) |
| { |
| /* check if we have an FQDN */ |
| if (strchr(Host, '.') == NULL) |
| { |
| oslHostAddr pAddr; |
| rtl_uString *hostName= NULL; |
| |
| rtl_string2UString( |
| &hostName, Host, strlen(Host), |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| OSL_ASSERT(hostName != 0); |
| |
| /* no, determine it via dns */ |
| pAddr = osl_createHostAddrByName(hostName); |
| rtl_uString_release (hostName); |
| |
| if (pAddr && pAddr->pHostName) |
| memcpy(LocalHostname, pAddr->pHostName->buffer, sizeof(sal_Unicode)*(rtl_ustr_getLength(pAddr->pHostName->buffer)+1)); |
| else |
| memset(LocalHostname, 0, sizeof(LocalHostname)); |
| |
| osl_destroyHostAddr ((oslHostAddr)pAddr); |
| } |
| } |
| } |
| |
| if (rtl_ustr_getLength(LocalHostname) > 0) |
| { |
| rtl_uString_newFromStr (strLocalHostname, LocalHostname); |
| return osl_Socket_Ok; |
| } |
| |
| return osl_Socket_Error; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_resolveHostname */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString* strHostname) |
| { |
| oslHostAddr pAddr= |
| (oslHostAddr )osl_createHostAddrByName (strHostname); |
| if (pAddr) |
| { |
| oslSocketAddr SockAddr = osl_copySocketAddr( pAddr->pSockAddr ); |
| osl_destroyHostAddr(pAddr); |
| return (SockAddr); |
| } |
| return ((oslSocketAddr)NULL); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getServicePort */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_getServicePort ( |
| rtl_uString* strServicename, |
| rtl_uString* strProtocol) |
| { |
| struct servent* ps; |
| |
| rtl_String *str_Servicename=NULL; |
| rtl_String *str_Protocol=NULL; |
| |
| rtl_uString2String( |
| &str_Servicename, |
| rtl_uString_getStr(strServicename), |
| rtl_uString_getLength(strServicename), |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| rtl_uString2String( |
| &str_Protocol, |
| rtl_uString_getStr(strProtocol), |
| rtl_uString_getLength(strProtocol), |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| |
| ps= getservbyname( |
| rtl_string_getStr(str_Servicename), |
| rtl_string_getStr(str_Protocol)); |
| |
| rtl_string_release( str_Servicename ); |
| rtl_string_release( str_Protocol ); |
| |
| if (ps != 0) |
| return ntohs(ps->s_port); |
| |
| return OSL_INVALID_PORT; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_destroySocketAddr */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr) |
| { |
| __osl_destroySocketAddr( pAddr ); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getFamilyOfSocketAddr */ |
| /*****************************************************************************/ |
| oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr) |
| { |
| if (pAddr) |
| return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family); |
| else |
| return osl_Socket_FamilyInvalid; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getInetPortOfSocketAddr */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr) |
| { |
| if( pAddr ) |
| { |
| struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr); |
| |
| if ( (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))) |
| return ntohs(pSystemInetAddr->sin_port); |
| } |
| return OSL_INVALID_PORT; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_setInetPortOfSocketAddr */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_setInetPortOfSocketAddr ( |
| oslSocketAddr pAddr, |
| sal_Int32 Port) |
| { |
| if (pAddr == NULL) |
| return sal_False; |
| |
| struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr); |
| |
| if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) |
| return sal_False; |
| |
| pSystemInetAddr->sin_port= htons((short)Port); |
| return sal_True; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getHostnameOfSocketAddr */ |
| /*****************************************************************************/ |
| oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr ( |
| oslSocketAddr Addr, |
| rtl_uString **strHostName) |
| { |
| oslHostAddr pAddr= osl_createHostAddrByAddr (Addr); |
| |
| if (pAddr) |
| { |
| rtl_uString_newFromString(strHostName, pAddr->pHostName); |
| |
| osl_destroyHostAddr(pAddr); |
| |
| return osl_Socket_Ok; |
| } |
| |
| return osl_Socket_Error; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getDottedInetAddrOfSocketAddr */ |
| /*****************************************************************************/ |
| oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr ( |
| oslSocketAddr pAddr, |
| rtl_uString **strDottedInetAddr) |
| { |
| sal_Char *pDotted; |
| |
| if (pAddr == NULL) |
| return osl_Socket_Error; |
| |
| struct sockaddr_in *pSystemInetAddr = (struct sockaddr_in*) &(pAddr->m_sockaddr); |
| if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet)) |
| return osl_Socket_Error; |
| |
| pDotted = inet_ntoa (pSystemInetAddr->sin_addr); |
| rtl_string2UString( |
| strDottedInetAddr, pDotted, strlen (pDotted), |
| RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); |
| OSL_ASSERT(*strDottedInetAddr != 0); |
| |
| return osl_Socket_Ok; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_createSocket */ |
| /*****************************************************************************/ |
| oslSocket SAL_CALL osl_createSocket ( |
| oslAddrFamily Family, |
| oslSocketType Type, |
| oslProtocol Protocol) |
| { |
| /* alloc memory */ |
| oslSocket pSocket = __osl_createSocketImpl(0); |
| |
| if (pSocket == NULL) |
| return 0; |
| |
| /* create socket */ |
| pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family), |
| TYPE_TO_NATIVE(Type), |
| PROTOCOL_TO_NATIVE(Protocol)); |
| |
| /* creation failed => free memory */ |
| if(pSocket->m_Socket == OSL_INVALID_SOCKET) |
| { |
| __osl_destroySocketImpl(pSocket); |
| pSocket= 0; |
| } |
| else |
| { |
| pSocket->m_Flags = 0; |
| pSocket->m_CloseCallback = NULL; |
| pSocket->m_CallbackArg = NULL; |
| } |
| |
| return pSocket; |
| } |
| |
| void SAL_CALL osl_acquireSocket( oslSocket pSocket ) |
| { |
| osl_incrementInterlockedCount( &(pSocket->m_nRefCount) ); |
| } |
| |
| void SAL_CALL osl_releaseSocket( oslSocket pSocket ) |
| { |
| if( pSocket && 0 == osl_decrementInterlockedCount( &(pSocket->m_nRefCount) ) ) |
| { |
| osl_closeSocket( pSocket ); |
| __osl_destroySocketImpl( pSocket ); |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* osl_closeSocket */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_closeSocket(oslSocket pSocket) |
| { |
| /* socket already invalid */ |
| if(pSocket==0) |
| return; |
| |
| /* close */ |
| closesocket(pSocket->m_Socket); |
| |
| pSocket->m_Socket = OSL_INVALID_SOCKET; |
| |
| /* registrierten Callback ausfuehren */ |
| if (pSocket->m_CloseCallback != NULL) |
| { |
| pSocket->m_CloseCallback(pSocket->m_CallbackArg); |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getLocalAddrOfSocket */ |
| /* Note that I rely on the fact that oslSocketAddr and struct sockaddr */ |
| /* are the same! I don't like it very much but see no other easy way */ |
| /* to conceal the struct sockaddr from the eyes of the user. */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket) |
| { |
| struct sockaddr Addr; |
| int AddrLen; |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return ((oslSocketAddr)NULL); |
| |
| AddrLen= sizeof(struct sockaddr); |
| |
| if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR) |
| return ((oslSocketAddr)NULL); |
| |
| oslSocketAddr pAddr = __osl_createSocketAddrFromSystem( &Addr ); |
| return pAddr; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getPeerAddrOfSocket */ |
| /*****************************************************************************/ |
| oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket) |
| { |
| struct sockaddr Addr; |
| int AddrLen; |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return ((oslSocketAddr)NULL); |
| |
| AddrLen= sizeof(struct sockaddr); |
| |
| if (getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR) |
| return ((oslSocketAddr)NULL); |
| |
| oslSocketAddr pAddr = __osl_createSocketAddrFromSystem( &Addr ); |
| return pAddr; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_bindAddrToSocket */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_bindAddrToSocket ( oslSocket pSocket, oslSocketAddr pAddr) |
| { |
| OSL_ASSERT( pAddr ); |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| return (bind(pSocket->m_Socket, |
| &(pAddr->m_sockaddr), |
| sizeof(struct sockaddr)) != OSL_SOCKET_ERROR); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_connectSocketTo */ |
| /*****************************************************************************/ |
| oslSocketResult SAL_CALL osl_connectSocketTo ( |
| oslSocket pSocket, |
| oslSocketAddr pAddr, |
| const TimeValue* pTimeout) |
| { |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_Error; |
| |
| if (pAddr == NULL) /* EDESTADDRREQ */ |
| return osl_Socket_Error; |
| |
| if (!__osl_attemptSocketDialupImpl()) /* ENETDOWN */ |
| return osl_Socket_Error; |
| |
| if (pTimeout == NULL) |
| { |
| if(connect(pSocket->m_Socket, |
| &(pAddr->m_sockaddr), |
| sizeof(struct sockaddr)) == OSL_SOCKET_ERROR) |
| return osl_Socket_Error; |
| else |
| return osl_Socket_Ok; |
| } |
| else |
| { |
| fd_set fds; |
| int error; |
| struct timeval tv; |
| unsigned long Param; |
| oslSocketResult Result= osl_Socket_Ok; |
| |
| if (pSocket->m_Flags & OSL_SOCKET_FLAGS_NONBLOCKING) |
| { |
| if (connect(pSocket->m_Socket, |
| &(pAddr->m_sockaddr), |
| sizeof(struct sockaddr)) == OSL_SOCKET_ERROR) |
| { |
| switch (WSAGetLastError()) |
| { |
| case WSAEWOULDBLOCK: |
| case WSAEINPROGRESS: |
| return osl_Socket_InProgress; |
| |
| default: |
| return osl_Socket_Error; |
| } |
| } |
| else |
| return osl_Socket_Ok; |
| } |
| |
| /* set socket temporarily to non-blocking */ |
| Param= 1; |
| OSL_VERIFY(ioctlsocket( |
| pSocket->m_Socket, FIONBIO, &Param) != OSL_SOCKET_ERROR); |
| |
| /* initiate connect */ |
| if (connect(pSocket->m_Socket, |
| &(pAddr->m_sockaddr), |
| sizeof(struct sockaddr)) != OSL_SOCKET_ERROR) |
| { |
| /* immediate connection */ |
| |
| Param= 0; |
| ioctlsocket(pSocket->m_Socket, FIONBIO, &Param); |
| |
| return osl_Socket_Ok; |
| } |
| else |
| { |
| error = WSAGetLastError(); |
| |
| /* really an error or just delayed? */ |
| if (error != WSAEWOULDBLOCK && error != WSAEINPROGRESS) |
| { |
| Param= 0; |
| ioctlsocket(pSocket->m_Socket, FIONBIO, &Param); |
| |
| return osl_Socket_Error; |
| } |
| } |
| |
| /* prepare select set for socket */ |
| FD_ZERO(&fds); |
| FD_SET(pSocket->m_Socket, &fds); |
| |
| /* divide milliseconds into seconds and microseconds */ |
| tv.tv_sec= pTimeout->Seconds; |
| tv.tv_usec= pTimeout->Nanosec / 1000L; |
| |
| /* select */ |
| error= select(pSocket->m_Socket+1, |
| 0, |
| &fds, |
| 0, |
| &tv); |
| |
| if (error > 0) /* connected */ |
| { |
| OSL_POSTCOND( |
| FD_ISSET(pSocket->m_Socket, &fds), |
| "osl_connectSocketTo(): select returned but socket not set\n"); |
| |
| Result= osl_Socket_Ok; |
| |
| } |
| else if(error < 0) /* error */ |
| { |
| /* errno == EBADF: most probably interrupted by close() */ |
| if(WSAGetLastError() == WSAEBADF) |
| { |
| /* do not access pSockImpl because it is about to be or */ |
| /* already destroyed */ |
| return osl_Socket_Interrupted; |
| } |
| else |
| Result= osl_Socket_Error; |
| |
| } |
| else /* timeout */ |
| Result= osl_Socket_TimedOut; |
| |
| |
| /* clean up */ |
| Param= 0; |
| ioctlsocket(pSocket->m_Socket, FIONBIO, &Param); |
| |
| return Result; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* osl_listenOnSocket */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_listenOnSocket ( |
| oslSocket pSocket, |
| sal_Int32 MaxPendingConnections) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| return (listen(pSocket->m_Socket, |
| MaxPendingConnections == -1 ? |
| SOMAXCONN : |
| MaxPendingConnections) != OSL_SOCKET_ERROR); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_acceptConnectionOnSocket */ |
| /*****************************************************************************/ |
| oslSocket SAL_CALL osl_acceptConnectionOnSocket ( |
| oslSocket pSocket, |
| oslSocketAddr* ppAddr) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return ((oslSocket)NULL); |
| |
| SOCKET Connection; |
| if(ppAddr) |
| { |
| if( *ppAddr ) |
| { |
| osl_destroySocketAddr( *ppAddr ); |
| *ppAddr = 0; |
| } |
| int AddrLen= sizeof(struct sockaddr); |
| |
| /* user wants to know peer Addr */ |
| struct sockaddr Addr; |
| |
| Connection= accept(pSocket->m_Socket, &Addr, &AddrLen); |
| OSL_ASSERT(AddrLen == sizeof(struct sockaddr)); |
| |
| if(Connection != OSL_SOCKET_ERROR) |
| *ppAddr= __osl_createSocketAddrFromSystem(&Addr); |
| else |
| *ppAddr = NULL; |
| } |
| else |
| { |
| /* user is not interested in peer-addr */ |
| Connection= accept(pSocket->m_Socket, 0, 0); |
| } |
| |
| /* accept failed? */ |
| if(Connection == OSL_SOCKET_ERROR) |
| return ((oslSocket)NULL); |
| |
| /* alloc memory */ |
| oslSocket pConnectionSocket; |
| pConnectionSocket= __osl_createSocketImpl(Connection); |
| |
| pConnectionSocket->m_Flags = 0; |
| pConnectionSocket->m_CloseCallback = NULL; |
| pConnectionSocket->m_CallbackArg = NULL; |
| |
| return pConnectionSocket; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_receiveSocket */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_receiveSocket ( |
| oslSocket pSocket, |
| void* pBuffer, |
| sal_uInt32 BytesToRead, |
| oslSocketMsgFlag Flag) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_Error; |
| |
| return recv(pSocket->m_Socket, |
| (sal_Char*)pBuffer, |
| BytesToRead, |
| MSG_FLAG_TO_NATIVE(Flag)); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_receiveFromSocket */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_receiveFromSocket ( |
| oslSocket pSocket, |
| oslSocketAddr SenderAddr, |
| void* pBuffer, |
| sal_uInt32 BufferSize, |
| oslSocketMsgFlag Flag) |
| { |
| struct sockaddr *pSystemSockAddr = 0; |
| int AddrLen = 0; |
| if( SenderAddr ) |
| { |
| AddrLen = sizeof( struct sockaddr ); |
| pSystemSockAddr = &(SenderAddr->m_sockaddr); |
| } |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_Error; |
| |
| return recvfrom(pSocket->m_Socket, |
| (sal_Char*)pBuffer, |
| BufferSize, |
| MSG_FLAG_TO_NATIVE(Flag), |
| pSystemSockAddr, |
| &AddrLen); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_sendSocket */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_sendSocket ( |
| oslSocket pSocket, |
| const void* pBuffer, |
| sal_uInt32 BytesToSend, |
| oslSocketMsgFlag Flag) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_Error; |
| |
| return send(pSocket->m_Socket, |
| (sal_Char*)pBuffer, |
| BytesToSend, |
| MSG_FLAG_TO_NATIVE(Flag)); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_sendToSocket */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_sendToSocket ( |
| oslSocket pSocket, |
| oslSocketAddr ReceiverAddr, |
| const void* pBuffer, |
| sal_uInt32 BytesToSend, |
| oslSocketMsgFlag Flag) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_Error; |
| |
| /* ReceiverAddr might be 0 when used on a connected socket. */ |
| /* Then sendto should behave like send. */ |
| |
| struct sockaddr *pSystemSockAddr = 0; |
| if( ReceiverAddr ) |
| pSystemSockAddr = &(ReceiverAddr->m_sockaddr); |
| |
| return sendto(pSocket->m_Socket, |
| (sal_Char*)pBuffer, |
| BytesToSend, |
| MSG_FLAG_TO_NATIVE(Flag), |
| pSystemSockAddr, |
| pSystemSockAddr == 0 ? 0 : sizeof(struct sockaddr)); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_readSocket */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_readSocket( oslSocket pSocket, void *pBuffer, sal_Int32 n ) |
| { |
| sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer; |
| |
| OSL_ASSERT( pSocket); |
| |
| /* loop until all desired bytes were read or an error occured */ |
| sal_uInt32 BytesRead= 0; |
| sal_uInt32 BytesToRead= n; |
| while (BytesToRead > 0) |
| { |
| sal_Int32 RetVal; |
| RetVal= osl_receiveSocket(pSocket, |
| Ptr, |
| BytesToRead, |
| osl_Socket_MsgNormal); |
| |
| /* error occured? */ |
| if(RetVal <= 0) |
| { |
| break; |
| } |
| |
| BytesToRead -= RetVal; |
| BytesRead += RetVal; |
| Ptr += RetVal; |
| } |
| |
| return BytesRead; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_writeSocket */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_writeSocket( oslSocket pSocket, const void *pBuffer, sal_Int32 n ) |
| { |
| OSL_ASSERT( pSocket ); |
| |
| /* loop until all desired bytes were send or an error occured */ |
| sal_uInt32 BytesSend= 0; |
| sal_uInt32 BytesToSend= n; |
| sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer; |
| while (BytesToSend > 0) |
| { |
| sal_Int32 RetVal; |
| |
| RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal); |
| |
| /* error occured? */ |
| if(RetVal <= 0) |
| { |
| break; |
| } |
| |
| BytesToSend -= RetVal; |
| BytesSend += RetVal; |
| Ptr += RetVal; |
| |
| } |
| return BytesSend; |
| } |
| |
| |
| /*****************************************************************************/ |
| /* osl_isReceiveReady */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_isReceiveReady ( |
| oslSocket pSocket, |
| const TimeValue* pTimeout) |
| { |
| fd_set fds; |
| struct timeval tv; |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| FD_ZERO(&fds); |
| FD_SET(pSocket->m_Socket, &fds); |
| |
| if (pTimeout) |
| { |
| tv.tv_sec = pTimeout->Seconds; |
| tv.tv_usec = pTimeout->Nanosec / 1000L; |
| } |
| |
| return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */ |
| &fds, /* check read operations */ |
| 0, /* check write ops */ |
| 0, /* ckeck for OOB */ |
| (pTimeout) ? &tv : 0)==1); /* use timeout? */ |
| } |
| |
| /*****************************************************************************/ |
| /* osl_isSendReady */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_isSendReady ( |
| oslSocket pSocket, |
| const TimeValue* pTimeout) |
| { |
| fd_set fds; |
| struct timeval tv; |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| FD_ZERO(&fds); |
| FD_SET(pSocket->m_Socket, &fds); |
| |
| if (pTimeout) |
| { |
| tv.tv_sec = pTimeout->Seconds; |
| tv.tv_usec = pTimeout->Nanosec / 1000L; |
| } |
| |
| return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */ |
| 0, /* check read operations */ |
| &fds, /* check write ops */ |
| 0, /* ckeck for OOB */ |
| (pTimeout) ? &tv : 0)==1); /* use timeout? */ |
| } |
| |
| /*****************************************************************************/ |
| /* osl_isExceptionPending */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_isExceptionPending ( |
| oslSocket pSocket, |
| const TimeValue* pTimeout) |
| { |
| fd_set fds; |
| struct timeval tv; |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| FD_ZERO(&fds); |
| FD_SET(pSocket->m_Socket, &fds); |
| |
| if (pTimeout) |
| { |
| tv.tv_sec = pTimeout->Seconds; |
| tv.tv_usec = pTimeout->Nanosec / 1000L; |
| } |
| |
| return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */ |
| 0, /* check read operations */ |
| 0, /* check write ops */ |
| &fds, /* ckeck for OOB */ |
| (pTimeout) ? &tv : 0)==1); /* use timeout? */ |
| } |
| |
| /*****************************************************************************/ |
| /* osl_shutdownSocket */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_shutdownSocket ( |
| oslSocket pSocket, |
| oslSocketDirection Direction) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| return (shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction))==0); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getSocketOption */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_getSocketOption ( |
| oslSocket pSocket, |
| oslSocketOptionLevel Level, |
| oslSocketOption Option, |
| void* pBuffer, |
| sal_uInt32 BufferLen) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_Error; |
| |
| if (getsockopt(pSocket->m_Socket, |
| OPTION_LEVEL_TO_NATIVE(Level), |
| OPTION_TO_NATIVE(Option), |
| (sal_Char*)pBuffer, |
| (int*)&BufferLen) == -1) |
| { |
| return -1; |
| } |
| |
| return (sal_Int32)BufferLen; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_setSocketOption */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_setSocketOption ( |
| oslSocket pSocket, |
| oslSocketOptionLevel Level, |
| oslSocketOption Option, |
| void* pBuffer, |
| sal_uInt32 BufferLen) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| return(setsockopt(pSocket->m_Socket, |
| OPTION_LEVEL_TO_NATIVE(Level), |
| OPTION_TO_NATIVE(Option), |
| (sal_Char*)pBuffer, |
| BufferLen) == 0); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_enableNonBlockingMode */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_enableNonBlockingMode ( oslSocket pSocket, sal_Bool On) |
| { |
| unsigned long Param= On ? 1 : 0; |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| pSocket->m_Flags = Param ? |
| (pSocket->m_Flags | OSL_SOCKET_FLAGS_NONBLOCKING) : |
| (pSocket->m_Flags & ~OSL_SOCKET_FLAGS_NONBLOCKING) ; |
| |
| return ( |
| ioctlsocket(pSocket->m_Socket, FIONBIO, &Param) != OSL_SOCKET_ERROR); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_isNonBlockingMode */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket) |
| { |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return sal_False; |
| |
| return (sal_Bool)((pSocket->m_Flags & OSL_SOCKET_FLAGS_NONBLOCKING) != 0); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getSocketType */ |
| /*****************************************************************************/ |
| oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket) |
| { |
| int Type=0; |
| int TypeSize= sizeof(Type); |
| |
| if (pSocket == NULL) /* ENOTSOCK */ |
| return osl_Socket_TypeInvalid; |
| |
| if(getsockopt(pSocket->m_Socket, |
| OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket), |
| OPTION_TO_NATIVE(osl_Socket_OptionType), |
| (sal_Char *)&Type, |
| &TypeSize) == -1) |
| { |
| /* error */ |
| return osl_Socket_TypeInvalid; |
| } |
| |
| return TYPE_FROM_NATIVE(Type); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getLastSocketErrorDescription */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_getLastSocketErrorDescription ( |
| oslSocket /*Socket*/, |
| rtl_uString **strError) |
| { |
| int error; |
| |
| switch(error = WSAGetLastError()) |
| { |
| case WSAENOTSOCK: |
| rtl_uString_newFromAscii (strError, "WSAENOTSOCK, Socket operation on non-socket. A socket created in one process is used by another process."); |
| break; |
| |
| case WSAEDESTADDRREQ: |
| rtl_uString_newFromAscii (strError, "WSAEDESTADDRREQ, Destination Addr required"); |
| break; |
| |
| case WSAEMSGSIZE: |
| rtl_uString_newFromAscii (strError, "WSAEMSGSIZE, Message too long"); |
| break; |
| |
| case WSAEPROTOTYPE: |
| rtl_uString_newFromAscii (strError, "WSAEPROTOTYPE, Protocol wrong type for socket"); |
| break; |
| |
| case WSAENOPROTOOPT: |
| rtl_uString_newFromAscii (strError, "WSAENOPROTOOPT, Protocol not available"); |
| break; |
| |
| case WSAEPROTONOSUPPORT: |
| rtl_uString_newFromAscii (strError, "WSAEPROTONOSUPPORT, Protocol not supported"); |
| break; |
| |
| case WSAESOCKTNOSUPPORT: |
| rtl_uString_newFromAscii (strError, "WSAESOCKTNOSUPPORT, Socket type not supported"); |
| break; |
| |
| case WSAEOPNOTSUPP: |
| rtl_uString_newFromAscii (strError, "WSAEOPNOTSUPP, Operation not supported on socket"); |
| break; |
| |
| case WSAEPFNOSUPPORT: |
| rtl_uString_newFromAscii (strError, "WSAEPFNOSUPPORT, Protocol family not supported"); |
| break; |
| |
| case WSAEAFNOSUPPORT: |
| rtl_uString_newFromAscii (strError, "WSEAFNOSUPPORT, Addr family not supported by protocol family"); |
| break; |
| |
| case WSAEADDRINUSE: |
| rtl_uString_newFromAscii (strError, "WSAEADDRINUSE, Triggered by bind() because a process went down without closing a socket."); |
| break; |
| |
| case WSAEADDRNOTAVAIL: |
| rtl_uString_newFromAscii (strError, "WSAEADDRNOTAVAIL, Can't assign requested Addr"); |
| break; |
| |
| case WSAENETDOWN: |
| rtl_uString_newFromAscii (strError, "WSAENETDOWN, Network is down"); |
| break; |
| |
| case WSAENETUNREACH: |
| rtl_uString_newFromAscii (strError, "WSAENETUNREACH, Network is unreachable"); |
| break; |
| |
| case WSAENETRESET: |
| rtl_uString_newFromAscii (strError, "WSAENETRESET, Network dropped connection or reset"); |
| break; |
| |
| case WSAECONNABORTED: |
| rtl_uString_newFromAscii (strError, "WSAECONNABORTED, Software caused connection abort"); |
| break; |
| |
| case WSAECONNRESET: |
| rtl_uString_newFromAscii (strError, "WSAECONNRESET, Connection reset by peer"); |
| break; |
| |
| case WSAENOBUFS: |
| rtl_uString_newFromAscii (strError, "WSAENOBUFS, No buffer space available."); |
| break; |
| |
| case WSAEISCONN: |
| rtl_uString_newFromAscii (strError, "WSAEISCONN, Socket is already connected"); |
| break; |
| |
| case WSAENOTCONN: |
| rtl_uString_newFromAscii (strError, "WSAENOTCONN, Socket is not connected"); |
| break; |
| |
| case WSAESHUTDOWN: |
| rtl_uString_newFromAscii (strError, "WSAESHUTDOWN, Can't send after socket shutdown"); |
| break; |
| |
| case WSAETIMEDOUT: |
| rtl_uString_newFromAscii (strError, "WSAETIMEDOUT, Connection timed out"); |
| break; |
| |
| case WSAECONNREFUSED: |
| rtl_uString_newFromAscii (strError, "WSAECONNREFUSED, Connection refused"); |
| break; |
| |
| case WSAEHOSTDOWN: |
| rtl_uString_newFromAscii (strError, "WSAEHOSTDOWN, Networking subsystem not started"); |
| break; |
| |
| case WSAEHOSTUNREACH: |
| rtl_uString_newFromAscii (strError, "WSAEHOSTUNREACH, No route to host"); |
| break; |
| |
| case WSAEWOULDBLOCK: |
| rtl_uString_newFromAscii (strError, "WSAEWOULDBLOCK, Operation would block"); |
| break; |
| |
| case WSAEINPROGRESS: |
| rtl_uString_newFromAscii (strError, "WSAEINPROGRESS, Operation now in progress"); |
| break; |
| |
| case WSAEALREADY: |
| rtl_uString_newFromAscii (strError, "WSAEALREADY, Operation already in progress"); |
| break; |
| |
| case WSAEINTR: |
| rtl_uString_newFromAscii (strError, "WSAEALREADY, Operation was interrupted"); |
| break; |
| |
| case WSAEBADF: |
| rtl_uString_newFromAscii (strError, "WSAEBADF, Bad file number"); |
| break; |
| |
| case WSAEACCES: |
| rtl_uString_newFromAscii (strError, "WSAEACCES, Access is denied"); |
| break; |
| |
| case WSAEFAULT: |
| rtl_uString_newFromAscii (strError, "WSAEFAULT, Bad memory Addr"); |
| break; |
| |
| case WSAEINVAL: |
| rtl_uString_newFromAscii (strError, "WSAEINVAL, The socket has not been bound with bind() or is already connected"); |
| break; |
| |
| case WSAEMFILE: |
| rtl_uString_newFromAscii (strError, "WSAEMFILE, No more file descriptors are available"); |
| break; |
| |
| case WSAETOOMANYREFS: |
| rtl_uString_newFromAscii (strError, "WSAETOOMANYREFS, Undocumented WinSock error"); |
| break; |
| |
| case WSAENAMETOOLONG: |
| rtl_uString_newFromAscii (strError, "WSAENAMETOOLONG, Undocumented WinSock error"); |
| break; |
| |
| case WSAENOTEMPTY: |
| rtl_uString_newFromAscii (strError, "WSAENOTEMPTY, Undocumented WinSock error"); |
| break; |
| |
| case WSAEPROCLIM: |
| rtl_uString_newFromAscii (strError, "WSAEPROCLIM, Undocumented WinSock error"); |
| break; |
| |
| case WSAEUSERS: |
| rtl_uString_newFromAscii (strError, "WSAEUSERS, Undocumented WinSock error"); |
| break; |
| |
| case WSAEDQUOT: |
| rtl_uString_newFromAscii (strError, "WSAEDQUOT, Undocumented WinSock error"); |
| break; |
| |
| case WSAESTALE: |
| rtl_uString_newFromAscii (strError, "WSAESTALE, Undocumented WinSock error"); |
| break; |
| |
| case WSAEREMOTE: |
| rtl_uString_newFromAscii (strError, "WSAEREMOTE, Undocumented WinSock error"); |
| break; |
| |
| case WSAEDISCON: |
| rtl_uString_newFromAscii (strError, "WSAEDISCON, Circuit was gracefully terminated"); |
| break; |
| |
| case WSASYSNOTREADY: |
| rtl_uString_newFromAscii (strError, "WSASYSNOTREADY, The underlying network subsystem is not ready for network communication"); |
| break; |
| |
| case WSAVERNOTSUPPORTED: |
| rtl_uString_newFromAscii (strError, "WSAVERNOTSUPPORTED, The version of Windows Sockets API support requested is not provided by this particular Windows Sockets implementation"); |
| break; |
| |
| case WSANOTINITIALISED: |
| rtl_uString_newFromAscii (strError, "WSANOTINITIALISED, WSAStartup() has not been called"); |
| break; |
| |
| case WSAHOST_NOT_FOUND: |
| rtl_uString_newFromAscii (strError, "WSAHOST_NOT_FOUND, Authoritative answer host not found"); |
| break; |
| |
| case WSATRY_AGAIN: |
| rtl_uString_newFromAscii (strError, "WSATRY_AGAIN, Non-authoritative answer host not found or SERVERFAIL"); |
| break; |
| |
| case WSANO_RECOVERY: |
| rtl_uString_newFromAscii (strError, "WSANO_RECOVERY, Non recoverable errors, FORMERR, REFUSED, NOTIMP"); |
| break; |
| |
| case WSANO_DATA: |
| rtl_uString_newFromAscii (strError, "WSANO_DATA or WSANO_ADDRESS, Valid name, no data record of requested type"); |
| break; |
| |
| default: |
| { |
| sal_Unicode message[128]; |
| |
| wsprintfW(reinterpret_cast<LPWSTR>(message), L"Unknown WinSock Error Number %d", error); |
| rtl_uString_newFromStr (strError, message); |
| } |
| |
| return; |
| |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* osl_getLastSocketError */ |
| /*****************************************************************************/ |
| oslSocketError SAL_CALL osl_getLastSocketError(oslSocket /*Socket*/) |
| { |
| return ERROR_FROM_NATIVE(WSAGetLastError()); |
| } |
| |
| /*****************************************************************************/ |
| /* SocketSet */ |
| /*****************************************************************************/ |
| typedef struct _TSocketSetImpl |
| { |
| fd_set m_Set; /* the set of descriptors */ |
| |
| } TSocketSetImpl; |
| |
| /*****************************************************************************/ |
| /* osl_createSocketSet */ |
| /*****************************************************************************/ |
| oslSocketSet SAL_CALL osl_createSocketSet() |
| { |
| TSocketSetImpl* pSet; |
| |
| pSet = (TSocketSetImpl*) rtl_allocateMemory(sizeof(TSocketSetImpl)); |
| |
| if(pSet) |
| { |
| FD_ZERO(&pSet->m_Set); |
| } |
| |
| return (oslSocketSet)pSet; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_destroySocketSet */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_destroySocketSet (oslSocketSet Set) |
| { |
| if(Set) |
| rtl_freeMemory(Set); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_clearSocketSet */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_clearSocketSet (oslSocketSet Set) |
| { |
| TSocketSetImpl* pSet; |
| |
| pSet= (TSocketSetImpl*)Set; |
| |
| if (pSet) |
| FD_ZERO(&pSet->m_Set); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_addToSocketSet */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_addToSocketSet ( |
| oslSocketSet Set, |
| oslSocket Socket) |
| { |
| TSocketSetImpl* pSet; |
| oslSocketImpl* pSockImpl; |
| |
| pSet= (TSocketSetImpl*)Set; |
| pSockImpl= (oslSocketImpl*)Socket; |
| |
| if (pSet && pSockImpl) |
| FD_SET(pSockImpl->m_Socket, &pSet->m_Set); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_removeFromSocketSet */ |
| /*****************************************************************************/ |
| void SAL_CALL osl_removeFromSocketSet ( |
| oslSocketSet Set, |
| oslSocket Socket) |
| { |
| TSocketSetImpl* pSet; |
| oslSocketImpl* pSockImpl; |
| |
| pSet= (TSocketSetImpl*)Set; |
| pSockImpl= (oslSocketImpl*)Socket; |
| |
| if (pSet && pSockImpl) |
| FD_CLR(pSockImpl->m_Socket, &pSet->m_Set); |
| } |
| |
| /*****************************************************************************/ |
| /* osl_isInSocketSet */ |
| /*****************************************************************************/ |
| sal_Bool SAL_CALL osl_isInSocketSet ( |
| oslSocketSet Set, |
| oslSocket Socket) |
| { |
| TSocketSetImpl* pSet; |
| oslSocketImpl* pSockImpl; |
| |
| pSet= (TSocketSetImpl*)Set; |
| pSockImpl= (oslSocketImpl*)Socket; |
| |
| if (pSet && pSockImpl) |
| return (FD_ISSET(pSockImpl->m_Socket, &pSet->m_Set) != 0); |
| else |
| return sal_False; |
| } |
| |
| /*****************************************************************************/ |
| /* osl_demultiplexSocketEvents */ |
| /*****************************************************************************/ |
| sal_Int32 SAL_CALL osl_demultiplexSocketEvents ( |
| oslSocketSet IncomingSet, |
| oslSocketSet OutgoingSet, |
| oslSocketSet OutOfBandSet, |
| const TimeValue* pTimeout) |
| { |
| int MaxHandle= 0; |
| struct timeval tv; |
| TSocketSetImpl* pInSet; |
| TSocketSetImpl* pOutSet; |
| TSocketSetImpl* pOOBSet; |
| |
| if(pTimeout) |
| { |
| /* divide milliseconds into seconds and microseconds */ |
| tv.tv_sec = pTimeout->Seconds; |
| tv.tv_usec = pTimeout->Nanosec / 1000L; |
| } |
| |
| /* map opaque data to impl-types */ |
| pInSet= (TSocketSetImpl*)IncomingSet; |
| pOutSet= (TSocketSetImpl*)OutgoingSet; |
| pOOBSet= (TSocketSetImpl*)OutOfBandSet; |
| |
| return select(MaxHandle, /* redundant in WIN32 */ |
| pInSet ? &pInSet->m_Set : 0, |
| pOutSet ? &pOutSet->m_Set : 0, |
| pOOBSet ? &pOOBSet->m_Set : 0, |
| pTimeout ? &tv : 0); |
| } |
| |
| } |