summaryrefslogtreecommitdiff
path: root/sal/osl/os2/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/os2/socket.c')
-rw-r--r--sal/osl/os2/socket.c3097
1 files changed, 3097 insertions, 0 deletions
diff --git a/sal/osl/os2/socket.c b/sal/osl/os2/socket.c
new file mode 100644
index 000000000000..6c171016f798
--- /dev/null
+++ b/sal/osl/os2/socket.c
@@ -0,0 +1,3097 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/socket.h>
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+
+#include <rtl/alloc.h>
+
+#include <ctype.h>
+#include <sal/types.h>
+
+#include "sockimpl.h"
+
+
+/* defines for poll */
+#ifdef HAVE_POLL_H
+#undef HAVE_POLL_H
+#endif
+
+#if defined(LINUX) || defined(NETBSD) || defined ( FREEBSD ) || defined (MACOSX)
+#include <sys/poll.h>
+#define HAVE_POLL_H
+#endif /* HAVE_POLL_H */
+
+#if defined(SOLARIS)
+#include <poll.h>
+#define HAVE_POLL_H
+#endif /* SOLARIS */
+
+#ifndef HAVE_POLL_H
+#define POLLIN 0x0001
+#define POLLOUT 0x0002
+#define POLLPRI 0x0004
+#endif /* HAVE_POLL_H */
+
+
+/* defines for shutdown */
+#define SD_RECEIVE 0
+#define SD_SEND 1
+#define SD_BOTH 2
+
+
+/*
+ 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-address-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 address
+ formats into consideration (maybe a long dotted address
+ 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 -1
+#define OSL_SOCKET_ERROR -1
+
+
+/* Buffer size for gethostbyname */
+#define MAX_HOSTBUFFER_SIZE 2048
+
+/*****************************************************************************/
+/* enum oslAddrFamily */
+/*****************************************************************************/
+
+/* map */
+static unsigned long FamilyMap[]= {
+ AF_INET, /* osl_Socket_FamilyInet */
+ AF_IPX, /* osl_Socket_FamilyIpx */
+ 0 /* osl_Socket_FamilyInvalid */
+};
+
+/* reverse map */
+static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
+{
+ oslAddrFamily i= (oslAddrFamily)0;
+
+ while(i != osl_Socket_FamilyInvalid)
+ {
+ if(FamilyMap[i] == nativeType)
+ return i;
+ i = (oslAddrFamily) ( 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 sal_uInt32 ProtocolMap[]= {
+ 0, /* osl_Socket_ProtocolIp */
+ NSPROTO_IPX, /* osl_Socket_ProtocolIpx */
+ NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
+ NSPROTO_SPXII, /* osl_Socket_ProtocolSpxII */
+ 0 /* osl_Socket_ProtocolInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslProtocol osl_ProtocolFromNative(sal_uInt32 nativeType)
+{
+ oslProtocol i= (oslProtocol)0;
+
+ while(i != osl_Socket_ProtocolInvalid)
+ {
+ if(ProtocolMap[i] == nativeType)
+ return i;
+ i = (oslProtocol) ( i + 1);
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y)
+#define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
+
+
+/*****************************************************************************/
+/* enum oslSocketType */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 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(sal_uInt32 nativeType)
+{
+ oslSocketType i= (oslSocketType)0;
+
+ while(i != osl_Socket_TypeInvalid)
+ {
+ if(TypeMap[i] == nativeType)
+ return i;
+ i = (oslSocketType)(i + 1);
+ }
+
+ return i;
+}
+
+/* macros */
+#define TYPE_TO_NATIVE(x) TypeMap[x]
+#define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketOption */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 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 */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketOption osl_SocketOptionFromNative(sal_uInt32 nativeType)
+{
+ oslSocketOption i= (oslSocketOption)0;
+
+ while(i != osl_Socket_OptionInvalid)
+ {
+ if(OptionMap[i] == nativeType)
+ return i;
+ i = (oslSocketOption) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+/* macros */
+#define OPTION_TO_NATIVE(x) OptionMap[x]
+#define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketOptionLevel */
+/*****************************************************************************/
+
+static sal_uInt32 OptionLevelMap[]= {
+ SOL_SOCKET, /* osl_Socket_LevelSocket */
+ IPPROTO_TCP, /* osl_Socket_LevelTcp */
+ 0 /* osl_Socket_LevelInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketOptionLevel osl_SocketOptionLevelFromNative(sal_uInt32 nativeType)
+{
+ oslSocketOptionLevel i= (oslSocketOptionLevel)0;
+
+ while(i != osl_Socket_LevelInvalid)
+ {
+ if(OptionLevelMap[i] == nativeType)
+ return i;
+ i = (oslSocketOptionLevel) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+/* macros */
+#define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
+#define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketMsgFlag */
+/*****************************************************************************/
+
+static sal_uInt32 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 */
+ 0 /* osl_Socket_MsgInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketMsgFlag osl_SocketMsgFlagFromNative(sal_uInt32 nativeType)
+{
+ oslSocketMsgFlag i= (oslSocketMsgFlag)0;
+
+ while(i != osl_Socket_MsgInvalid)
+ {
+ if(SocketMsgFlagMap[i] == nativeType)
+ return i;
+ i = (oslSocketMsgFlag) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
+#define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketDirection */
+/*****************************************************************************/
+
+static sal_uInt32 SocketDirection[]= {
+ SD_RECEIVE, /* osl_Socket_DirRead */
+ SD_SEND, /* osl_Socket_DirWrite */
+ SD_BOTH, /* osl_Socket_DirReadWrite */
+ 0 /* osl_Socket_DirInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketDirection osl_SocketDirectionFromNative(sal_uInt32 nativeType)
+{
+ oslSocketDirection i= (oslSocketDirection)0;
+
+ while(i != osl_Socket_DirInvalid)
+ {
+ if(SocketDirection[i] == nativeType)
+ return i;
+ i = (oslSocketDirection) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define DIRECTION_TO_NATIVE(x) SocketDirection[x]
+#define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketError */
+/*****************************************************************************/
+
+static struct
+{
+ int errcode;
+ oslSocketError error;
+} SocketError[]= {
+ { 0, osl_Socket_E_None }, /* no error */
+ { ENOTSOCK, osl_Socket_E_NotSocket }, /* Socket operation on non-socket */
+ { EDESTADDRREQ, osl_Socket_E_DestAddrReq }, /* Destination address required */
+ { EMSGSIZE, osl_Socket_E_MsgSize }, /* Message too long */
+ { EPROTOTYPE, osl_Socket_E_Prototype }, /* Protocol wrong type for socket */
+ { ENOPROTOOPT, osl_Socket_E_NoProtocol }, /* Protocol not available */
+ { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */
+ { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport }, /* Socket type not supported */
+ { EOPNOTSUPP, osl_Socket_E_OpNotSupport }, /* Operation not supported on socket */
+ { EPFNOSUPPORT, osl_Socket_E_PfNoSupport }, /* Protocol family not supported */
+ { EAFNOSUPPORT, osl_Socket_E_AfNoSupport }, /* Address family not supported by */
+ /* protocol family */
+ { EADDRINUSE, osl_Socket_E_AddrInUse }, /* Address already in use */
+ { EADDRNOTAVAIL, osl_Socket_E_AddrNotAvail }, /* Can't assign requested address */
+ { ENETDOWN, osl_Socket_E_NetDown }, /* Network is down */
+ { ENETUNREACH, osl_Socket_E_NetUnreachable }, /* Network is unreachable */
+ { ENETRESET, osl_Socket_E_NetReset }, /* Network dropped connection because */
+ /* of reset */
+ { ECONNABORTED, osl_Socket_E_ConnAborted }, /* Software caused connection abort */
+ { ECONNRESET, osl_Socket_E_ConnReset }, /* Connection reset by peer */
+ { ENOBUFS, osl_Socket_E_NoBufferSpace }, /* No buffer space available */
+ { EISCONN, osl_Socket_E_IsConnected }, /* Socket is already connected */
+ { ENOTCONN, osl_Socket_E_NotConnected }, /* Socket is not connected */
+ { ESHUTDOWN, osl_Socket_E_Shutdown }, /* Can't send after socket shutdown */
+ { ETOOMANYREFS, osl_Socket_E_TooManyRefs }, /* Too many references: can't splice */
+ { ETIMEDOUT, osl_Socket_E_TimedOut }, /* Connection timed out */
+ { ECONNREFUSED, osl_Socket_E_ConnRefused }, /* Connection refused */
+ { EHOSTDOWN, osl_Socket_E_HostDown }, /* Host is down */
+ { EHOSTUNREACH, osl_Socket_E_HostUnreachable }, /* No route to host */
+ { EWOULDBLOCK, osl_Socket_E_WouldBlock }, /* call would block on non-blocking socket */
+ { EALREADY, osl_Socket_E_Already }, /* operation already in progress */
+ { EINPROGRESS, osl_Socket_E_InProgress }, /* operation now in progress */
+ { EAGAIN, osl_Socket_E_WouldBlock }, /* same as EWOULDBLOCK */
+ { -1, osl_Socket_E_InvalidError }
+};
+
+/* map */
+/* mfe: NOT USED
+static int osl_NativeFromSocketError(oslSocketError errorCode)
+{
+ int i = 0;
+
+ while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
+ (SocketError[i].error != errorCode)) i++;
+
+ return SocketError[i].errcode;
+}
+*/
+
+/* reverse map */
+static oslSocketError osl_SocketErrorFromNative(int nativeType)
+{
+ int i = 0;
+
+ while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
+ (SocketError[i].errcode != nativeType)) i++;
+
+ return SocketError[i].error;
+}
+
+/* macros */
+#define ERROR_TO_NATIVE(x) osl_NativeFromSocketError(x)
+#define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
+
+/*****************************************************************************/
+/* local function prototypes */
+/*****************************************************************************/
+
+oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
+ const sal_Char* pszDottedAddr, sal_Int32 Port);
+
+oslSocketAddr SAL_CALL osl_psz_createIpxSocketAddr (
+ const sal_Char NetNumber[4],
+ const sal_Char NodeNumber[6],
+ sal_uInt32 SocketNumber);
+
+oslHostAddr SAL_CALL osl_psz_createHostAddr (
+ const sal_Char *pszHostname, const oslSocketAddr Addr);
+
+oslHostAddr SAL_CALL osl_psz_createHostAddrByName (
+ const sal_Char *pszHostname);
+
+const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (
+ const oslHostAddr Addr);
+
+oslSocketResult SAL_CALL osl_psz_getLocalHostname (
+ sal_Char *pBuffer, sal_uInt32 nBufLen);
+
+oslSocketAddr SAL_CALL osl_psz_resolveHostname (
+ const sal_Char* pszHostname);
+
+sal_Int32 SAL_CALL osl_psz_getServicePort (
+ const sal_Char* pszServicename, const sal_Char* pszProtocol);
+
+oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr (
+ oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
+
+oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr (
+ oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
+
+void SAL_CALL osl_psz_getLastSocketErrorDescription (
+ oslSocket Socket, sal_Char* pBuffer, sal_uInt32 BufferSize);
+
+/*****************************************************************************/
+/* osl_create/destroy-SocketImpl */
+/*****************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+static sal_uInt32 g_nSocketImpl = 0;
+static sal_uInt32 g_nSocketAddr = 0;
+
+/* sorry, must be implemented otherwise */
+#if 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
+
+#endif /* OSL_DEBUG_LEVEL */
+
+
+oslSocket __osl_createSocketImpl(int Socket)
+{
+ oslSocket pSocket;
+
+ pSocket = (oslSocket)calloc(1, sizeof(struct oslSocketImpl));
+
+ pSocket->m_Socket = Socket;
+ pSocket->m_nLastError = 0;
+ pSocket->m_CloseCallback = 0;
+ pSocket->m_CallbackArg = 0;
+ pSocket->m_nRefCount = 1;
+
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_False;
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketImpl ++;
+#endif
+ return pSocket;
+}
+
+void __osl_destroySocketImpl(oslSocket Socket)
+{
+ if ( Socket != NULL)
+ free((struct oslSocketImpl *) Socket);
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketImpl --;
+#endif
+}
+
+static oslSocketAddr __osl_createSocketAddr( )
+{
+ oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr ++;
+#endif
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrWithFamily(
+ oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
+{
+ oslSocketAddr pAddr;
+
+ OSL_ASSERT( family == osl_Socket_FamilyInet );
+
+ 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( struct 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 */
+/*****************************************************************************/
+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;
+ oslSocketAddr pAddr;
+
+ 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);
+ }
+
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createInetSocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetSocketAddr (
+ rtl_uString *ustrDottedAddr,
+ sal_Int32 Port)
+{
+ rtl_String* strDottedAddr=0;
+ oslSocketAddr Addr;
+ sal_Char* pszDottedAddr=0;
+
+ if ( ustrDottedAddr != 0 )
+ {
+ rtl_uString2String( &strDottedAddr,
+ rtl_uString_getStr(ustrDottedAddr),
+ rtl_uString_getLength(ustrDottedAddr),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ pszDottedAddr = rtl_string_getStr(strDottedAddr);
+ }
+
+
+ Addr = osl_psz_createInetSocketAddr(pszDottedAddr, Port);
+
+ if ( strDottedAddr != 0 )
+ {
+ rtl_string_release(strDottedAddr);
+ }
+
+ return Addr;
+}
+
+oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
+ const sal_Char* pszDottedAddr,
+ sal_Int32 Port)
+{
+ oslSocketAddr pAddr = 0;
+ sal_Int32 Addr = inet_addr(pszDottedAddr);
+ if(Addr != -1)
+ {
+ /* valid dotted addr */
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , Addr );
+ }
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_setAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
+{
+ oslSocketResult res = osl_Socket_Error;
+
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( pByteSeq );
+
+ if( pAddr && pByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr;
+
+ OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
+ OSL_ASSERT( pByteSeq->nElements == 4 );
+
+ pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/*****************************************************************************/
+/* osl_getAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
+{
+ oslSocketResult res = osl_Socket_Error;
+
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( ppByteSeq );
+
+ 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;
+}
+
+
+/*****************************************************************************/
+/* _osl_getFullQualifiedDomainName */
+/*****************************************************************************/
+
+/** try to figure out a full-qualified hostname, by adding the current domain
+ as given by the domainname program to the given hostname.
+ This function MUST NOT call gethostbyname since pHostName allready points
+ to data returned by gethostname and would be garbled: use gethostname_r
+ instead!
+ */
+
+/* wrap around different interfaces to reentrant gethostbyname */
+static struct hostent* _osl_gethostbyname_r (
+ const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop)
+{
+
+#ifdef LINUX
+ struct hostent *__result; /* will be the same as result */
+ int __error;
+ __error = gethostbyname_r (name, result, buffer, buflen,
+ &__result, h_errnop);
+ return __error ? NULL : __result ;
+#elif defined OS2
+ // YD FIXME!!!
+ return 0;
+#else
+ return gethostbyname_r( name, result, buffer, buflen, h_errnop);
+#endif
+}
+
+static sal_Bool _osl_getDomainName (sal_Char *buffer, sal_Int32 bufsiz)
+{
+ sal_Bool result;
+ int p[2];
+
+ result = sal_False;
+
+#if 0 // YD 17/04/06 libc panic for fork() from thread!=1
+
+ if (pipe (p) == 0)
+ {
+ pid_t pid;
+ int nStatus;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ char *argv[] =
+ {
+ "/bin/domainname",
+ NULL
+ };
+
+ close (p[0]);
+ dup2 (p[1], 1);
+ close (p[1]);
+
+ execv ("/bin/domainname", argv);
+ // arriving here means exec failed
+ _exit(-1);
+ }
+ else if (pid > 0)
+ {
+ sal_Int32 k = 0, n = bufsiz;
+
+ close (p[1]);
+ if ((k = read (p[0], buffer, n - 1)) > 0)
+ {
+ buffer[k] = 0;
+ if (buffer[k - 1] == '\n')
+ buffer[k - 1] = 0;
+ result = sal_True;
+ }
+ close (p[0]);
+ waitpid (pid, &nStatus, 0);
+ }
+ else
+ {
+ close (p[0]);
+ close (p[1]);
+ }
+ }
+#endif // 0
+
+ return (result);
+}
+
+static sal_Char* _osl_getFullQualifiedDomainName (const sal_Char *pHostName)
+{
+# define DOMAINNAME_LENGTH 512
+ sal_uInt32 nLengthOfHostName;
+ static sal_uInt32 nLengthOfDomainName = 0;
+ static sal_Char *pDomainName = NULL;
+
+ sal_Char *pFullQualifiedName;
+#if 0 /* OBSOLETE */
+ FILE *pPipeToDomainnameExe;
+#endif /* OBSOLETE */
+
+ /* get a '\0' terminated domainname */
+
+ /* read default domainname default from environment */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char *pEnvDomain;
+
+ pEnvDomain = getenv ("STAR_OVERRIDE_DOMAINNAME");
+ if (pEnvDomain)
+ {
+ pDomainName = strdup (pEnvDomain);
+ nLengthOfDomainName = strlen (pDomainName);
+ }
+ }
+
+#if 1 /* NEW */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+
+ pDomainNameBuffer[0] = '\0';
+
+ if (_osl_getDomainName (pDomainNameBuffer, DOMAINNAME_LENGTH))
+ {
+ pDomainName = strdup (pDomainNameBuffer);
+ nLengthOfDomainName = strlen (pDomainName);
+ }
+ }
+
+#endif /* NEW */
+#if 0 /* OBSOLETE */
+#ifdef SCO
+
+ /* call 'domainname > /usr/tmp/some-tmp-file', since
+ popen read pclose do block or core-dump,
+ (even the pipe-stuff that comes with pthreads) */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char tmp_name[ L_tmpnam ];
+ FILE *tmp_file;
+ sal_Char domain_call [ L_tmpnam + 16 ] = "domainname > ";
+
+ tmp_name[0] = '\0';
+
+ tmpnam ( tmp_name );
+ strcat ( domain_call, tmp_name );
+ if ( (system ( domain_call ) == 0)
+ && ((tmp_file = fopen( tmp_name, "r" )) != NULL ) )
+ {
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+
+ pDomainNameBuffer[0] = '\0';
+
+ if ( fgets ( pDomainNameBuffer, DOMAINNAME_LENGTH, tmp_file ) )
+ {
+ pDomainName = strdup( pDomainNameBuffer );
+ nLengthOfDomainName = strlen( pDomainName );
+ if ( ( nLengthOfDomainName > 0 )
+ && ( pDomainName[ nLengthOfDomainName - 1] == '\n' ) )
+ pDomainName[ --nLengthOfDomainName ] = '\0';
+ }
+ fclose ( tmp_file );
+ }
+ unlink( tmp_name );
+ }
+
+#else /* !SCO */
+
+ /* read the domainname from pipe to the program domainname */
+ if ( (nLengthOfDomainName == 0)
+ && (pPipeToDomainnameExe = popen( "domainname", "r")) )
+ {
+ sal_Char c;
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+ sal_Char *pDomainNamePointer;
+
+ pDomainNameBuffer[0] = '\0';
+
+ pDomainNamePointer = pDomainNameBuffer;
+ while ( ((c = getc( pPipeToDomainnameExe )) != EOF)
+ && (nLengthOfDomainName < (DOMAINNAME_LENGTH - 1)) )
+ {
+ if (! isspace(c))
+ {
+ nLengthOfDomainName++ ;
+ *pDomainNamePointer++ = (sal_Char)c;
+ }
+ }
+ *pDomainNamePointer = '\0';
+ pDomainName = strdup( pDomainNameBuffer );
+
+ pclose( pPipeToDomainnameExe );
+ }
+
+#endif /* !SCO */
+#endif /* OBSOLETE */
+
+ /* compose hostname and domainname */
+ nLengthOfHostName = strlen( pHostName );
+ pFullQualifiedName = (sal_Char*) malloc( (nLengthOfHostName + 1
+ + nLengthOfDomainName + 1) * sizeof(sal_Char) );
+ memcpy( pFullQualifiedName, pHostName,
+ (nLengthOfHostName + 1) * sizeof(sal_Char) );
+
+ if ( nLengthOfDomainName > 0 )
+ {
+ /* fqdn = hostname + '.' + domainname + '\0' */
+ pFullQualifiedName[ nLengthOfHostName ] = '.';
+ memcpy( pFullQualifiedName + nLengthOfHostName + 1, pDomainName,
+ nLengthOfDomainName + 1 );
+ }
+
+ /* check whether full-qualified name and hostname point to the same host
+ * should almost always be true */
+ if ( nLengthOfDomainName > 0 )
+ {
+ struct hostent *pQualifiedHostByName;
+ struct hostent *pHostByName;
+ sal_Bool bHostsAreEqual;
+
+ /* buffer for calls to reentrant version of gethostbyname */
+ struct hostent aHostByName, aQualifiedHostByName;
+ sal_Char pHostBuffer[ MAX_HOSTBUFFER_SIZE ];
+ sal_Char pQualifiedHostBuffer[ MAX_HOSTBUFFER_SIZE ];
+ int nErrorNo;
+
+ pHostBuffer[0] = '\0';
+ pQualifiedHostBuffer[0] = '\0';
+
+ /* get list of addresses */
+ pQualifiedHostByName = _osl_gethostbyname_r (
+ pFullQualifiedName,
+ &aQualifiedHostByName, pQualifiedHostBuffer,
+ sizeof(pQualifiedHostBuffer), &nErrorNo );
+ pHostByName = _osl_gethostbyname_r (
+ pHostName,
+ &aHostByName, pHostBuffer,
+ sizeof(pHostBuffer), &nErrorNo );
+
+ /* compare addresses */
+ bHostsAreEqual = sal_False;
+ if ( pQualifiedHostByName && pHostByName )
+ {
+ sal_Char **p, **q;
+ struct in_addr in;
+
+ /* lists are expected to be (very) short */
+ for ( p = pQualifiedHostByName->h_addr_list; *p != NULL; p++ )
+ {
+ for ( q = pHostByName->h_addr_list; *q != NULL; q++ )
+ {
+ /* in.s_addr may be in_addr_t or uint32_t or heaven knows */
+ if ( memcmp( *p, *q, sizeof(in.s_addr) ) == 0 )
+ {
+ bHostsAreEqual = sal_True;
+ break;
+ }
+ }
+ if ( bHostsAreEqual )
+ break;
+ }
+ }
+
+ /* very strange case, but have to believe it: reduce the
+ * full qualified name to the unqualified host name */
+ if ( !bHostsAreEqual )
+ {
+ OSL_TRACE("_osl_getFullQualifiedDomainName: "
+ "suspect FQDN: %s\n", pFullQualifiedName);
+
+ pFullQualifiedName[ nLengthOfHostName ] = '\0';
+ pFullQualifiedName = (sal_Char*)realloc ( pFullQualifiedName,
+ (nLengthOfHostName + 1) * sizeof( sal_Char ));
+ }
+ }
+
+ /* always return a hostname looked up as carefully as possible
+ * this string must be freed by the caller */
+ return pFullQualifiedName;
+}
+
+/*****************************************************************************/
+/* _osl_isFullQualifiedDomainName */
+/*****************************************************************************/
+static sal_Bool _osl_isFullQualifiedDomainName (const sal_Char *pHostName)
+{
+ /* a FQDN (aka 'hostname.domain.top_level_domain' )
+ * is a name which contains a dot '.' in it ( would
+ * match as well for 'hostname.' but is good enough
+ * for now )*/
+ return (sal_Bool)( strchr( pHostName, (int)'.' ) != NULL );
+}
+
+/*****************************************************************************/
+/* oslHostAddr */
+/*****************************************************************************/
+struct oslHostAddrImpl
+{
+ sal_Char *pHostName;
+ oslSocketAddr pSockAddr;
+};
+
+static oslHostAddr _osl_hostentToHostAddr (const struct hostent *he)
+{
+ oslHostAddr pAddr= NULL;
+ oslSocketAddr pSockAddr = 0;
+
+
+ if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
+ return ((oslHostAddr)NULL);
+
+ //YD 18/06/2006 win32 does this with unicode, see socket.cxx
+ sal_Char *cn;
+ cn= (sal_Char *)malloc(strlen (he->h_name) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy(cn, he->h_name);
+
+#if 0 // YD 17/04/06 win32 doesn't it.
+ if (_osl_isFullQualifiedDomainName(he->h_name))
+ {
+ cn= (sal_Char *)malloc(strlen (he->h_name) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy(cn, he->h_name);
+ }
+ else
+ {
+ cn =_osl_getFullQualifiedDomainName (he->h_name);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+ }
+#endif
+
+ pSockAddr = __osl_createSocketAddr();
+ OSL_ASSERT(pSockAddr);
+ if (pSockAddr == NULL)
+ {
+ free(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pSockAddr->m_sockaddr.sa_family= he->h_addrtype;
+ if (pSockAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ struct sockaddr_in *sin= (struct sockaddr_in *)&(pSockAddr->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( pSockAddr );
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
+ OSL_ASSERT(pAddr);
+ if (pAddr == NULL)
+ {
+ __osl_destroySocketAddr( pSockAddr );
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= pSockAddr;
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddr (
+ rtl_uString *ustrHostname,
+ const oslSocketAddr Addr)
+{
+ oslHostAddr HostAddr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName = rtl_string_getStr(strHostname);
+ }
+
+ HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+
+ return HostAddr;
+}
+
+oslHostAddr SAL_CALL osl_psz_createHostAddr (
+ const sal_Char *pszHostname,
+ const oslSocketAddr pAddr)
+{
+ oslHostAddr pHostAddr;
+ sal_Char *cn;
+
+ OSL_ASSERT(pszHostname && pAddr);
+ if ((pszHostname == NULL) || (pAddr == NULL))
+ return ((oslHostAddr)NULL);
+
+ cn = (sal_Char *)malloc(strlen (pszHostname) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy (cn, pszHostname);
+
+ pHostAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
+ OSL_ASSERT(pHostAddr);
+ if (pAddr == NULL)
+ {
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pHostAddr->pHostName= cn;
+ pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
+
+ return pHostAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByName */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
+{
+ oslHostAddr HostAddr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName=rtl_string_getStr(strHostname);
+ }
+
+ HostAddr = osl_psz_createHostAddrByName(pszHostName);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+ return HostAddr;
+}
+
+oslHostAddr SAL_CALL osl_psz_createHostAddrByName (const sal_Char *pszHostname)
+{
+ struct hostent *he;
+ oslHostAddr addr;
+
+ static oslMutex mutex = NULL;
+
+ if (mutex == NULL)
+ mutex = osl_createMutex();
+
+ osl_acquireMutex(mutex);
+
+ he = gethostbyname((sal_Char *)pszHostname);
+ addr = _osl_hostentToHostAddr (he);
+
+ osl_releaseMutex(mutex);
+
+ return addr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
+{
+ OSL_ASSERT(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);
+ struct hostent *he;
+
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ return ((oslHostAddr)NULL);
+
+ he= gethostbyaddr((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 pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
+ else
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_getHostnameOfHostAddr (
+ const oslHostAddr Addr,
+ rtl_uString **ustrHostname)
+{
+ const sal_Char* pHostname=0;
+
+ pHostname = osl_psz_getHostnameOfHostAddr(Addr);
+
+ rtl_uString_newFromAscii (ustrHostname, pHostname);
+
+ return;
+}
+
+const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return pAddr->pHostName;
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_getSocketAddrOfHostAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return ((oslSocketAddr)(pAddr->pSockAddr));
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_destroyHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
+{
+ if (pAddr)
+ {
+ if (pAddr->pHostName)
+ free (pAddr->pHostName);
+ if (pAddr->pSockAddr)
+ osl_destroySocketAddr (pAddr->pSockAddr);
+ free (pAddr);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalHostname */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
+{
+ oslSocketResult Result;
+ sal_Char pszHostname[1024];
+
+ pszHostname[0] = '\0';
+
+ Result = osl_psz_getLocalHostname(pszHostname,sizeof(pszHostname));
+
+ rtl_uString_newFromAscii(ustrLocalHostname,pszHostname);
+
+ return Result;
+}
+
+oslSocketResult SAL_CALL osl_psz_getLocalHostname (
+ sal_Char *pBuffer, sal_uInt32 nBufLen)
+{
+ static sal_Char LocalHostname[256] = "";
+
+ if (strlen(LocalHostname) == 0)
+ {
+ const sal_Char *pStr;
+
+#ifdef SYSV
+ struct utsname uts;
+
+ if (uname(&uts) < 0)
+ return osl_Socket_Error;
+
+ if ((strlen(uts.nodename) + 1) > nBufLen)
+ return osl_Socket_Error;
+
+ strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
+#else /* BSD compatible */
+
+ if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
+ return osl_Socket_Error;
+ LocalHostname[sizeof(LocalHostname)-1] = 0;
+#endif /* SYSV */
+
+ /* check if we have an FQDN */
+ if (strchr(LocalHostname, '.') == NULL)
+ {
+ oslHostAddr Addr;
+
+ /* no, determine it via dns */
+ Addr = osl_psz_createHostAddrByName(LocalHostname);
+
+ if (Addr && (pStr = osl_psz_getHostnameOfHostAddr(Addr)) != NULL)
+ {
+#if 0 /* OBSOLETE */
+ sal_Char* pChr;
+#endif /* OBSOLETE */
+ strcpy(LocalHostname, pStr);
+
+#if 0 /* OBSOLETE */
+ /* already done by _osl_getFullQualifiedDomainName() with
+ much better heuristics, so this may be contraproductive */
+
+ /* no FQDN, last try append domain name */
+ if ((pChr = strchr(LocalHostname, '.')) == NULL)
+ {
+ FILE *fp;
+
+ pChr = &LocalHostname[strlen(LocalHostname)];
+
+ if ( (fp = popen("domainname", "r")) != 0 )
+ {
+ int c;
+
+ *pChr++ = '.';
+
+ while ((c = getc(fp)) != EOF)
+ {
+ if (! isspace(c))
+ *pChr++ = (sal_Char)c;
+ }
+
+ *pChr = '\0';
+
+ fclose(fp);
+ }
+ else
+ LocalHostname[0] = '\0';
+ }
+#endif /* OBSOLETE */
+
+ }
+ if (Addr)
+ osl_destroyHostAddr(Addr);
+ }
+ }
+
+ if (strlen(LocalHostname) > 0)
+ {
+ strncpy(pBuffer, LocalHostname, nBufLen);
+ pBuffer[nBufLen - 1] = '\0';
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_resolveHostname */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
+{
+ oslSocketAddr Addr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName = rtl_string_getStr(strHostname);
+ }
+
+
+ Addr = osl_psz_resolveHostname(pszHostName);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+
+ return Addr;
+}
+
+
+oslSocketAddr SAL_CALL osl_psz_resolveHostname(const sal_Char* pszHostname)
+{
+ struct oslHostAddrImpl *pAddr = (oslHostAddr)osl_psz_createHostAddrByName(pszHostname);
+
+ 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 *ustrServicename, rtl_uString *ustrProtocol)
+{
+ sal_Int32 nPort;
+ rtl_String* strServicename=0;
+ rtl_String* strProtocol=0;
+ sal_Char* pszServiceName=0;
+ sal_Char* pszProtocol=0;
+
+ if ( ustrServicename != 0 )
+ {
+ rtl_uString2String( &strServicename,
+ rtl_uString_getStr(ustrServicename),
+ rtl_uString_getLength(ustrServicename),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszServiceName = rtl_string_getStr(strServicename);
+ }
+
+ if ( ustrProtocol != 0 )
+ {
+ rtl_uString2String( &strProtocol,
+ rtl_uString_getStr(ustrProtocol),
+ rtl_uString_getLength(ustrProtocol),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszProtocol = rtl_string_getStr(strProtocol);
+ }
+
+ nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
+
+ if ( strServicename != 0 )
+ {
+ rtl_string_release(strServicename);
+ }
+
+ if ( strProtocol != 0 )
+ {
+ rtl_string_release(strProtocol);
+ }
+
+
+ return nPort;
+}
+
+
+sal_Int32 SAL_CALL osl_psz_getServicePort(const sal_Char* pszServicename,
+ const sal_Char* pszProtocol)
+{
+ struct servent* ps;
+
+ ps= getservbyname(pszServicename, pszProtocol);
+
+ 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)
+{
+ OSL_ASSERT(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)
+{
+ OSL_ASSERT(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)
+{
+ OSL_ASSERT(pAddr);
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+ if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ pSystemInetAddr->sin_port= htons((short)Port);
+ return sal_True;
+ }
+ }
+
+ /* this is not a inet-addr => can't set port */
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
+{
+ oslSocketResult Result;
+ sal_Char pszHostname[1024];
+
+ pszHostname[0] = '\0';
+
+ Result = osl_psz_getHostnameOfSocketAddr(Addr,pszHostname,sizeof(pszHostname));
+
+ rtl_uString_newFromAscii(ustrHostname,pszHostname);
+
+ return Result;
+}
+
+
+oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr,
+ sal_Char *pBuffer, sal_uInt32 BufferSize)
+{
+ oslHostAddr pHostAddr= (oslHostAddr )osl_createHostAddrByAddr(pAddr);
+
+ if (pHostAddr)
+ {
+ strncpy(pBuffer, pHostAddr->pHostName, BufferSize);
+
+ pBuffer[BufferSize - 1] = '\0';
+
+ osl_destroyHostAddr(pHostAddr);
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_getDottedInetAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
+{
+ oslSocketResult Result;
+ sal_Char pszDottedInetAddr[1024];
+
+ pszDottedInetAddr[0] = '\0';
+
+ Result = osl_psz_getDottedInetAddrOfSocketAddr(Addr,pszDottedInetAddr,sizeof(pszDottedInetAddr));
+
+ rtl_uString_newFromAscii(ustrDottedInetAddr,pszDottedInetAddr);
+
+ return Result;
+
+}
+
+oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr,
+ sal_Char *pBuffer, sal_uInt32 BufferSize)
+{
+ OSL_ASSERT(pAddr);
+
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr = ( struct sockaddr_in * ) &(pAddr->m_sockaddr);
+
+ if (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ strncpy(pBuffer, inet_ntoa(pSystemInetAddr->sin_addr), BufferSize);
+ pBuffer[BufferSize - 1] = '\0';
+
+ return osl_Socket_Ok;
+ }
+ }
+
+ return osl_Socket_Error;
+}
+
+#if 0 /* OBSOLETE */
+/*****************************************************************************/
+/* osl_getIpxNetNumber */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getIpxNetNumber(oslSocketAddr Addr,
+ oslSocketIpxNetNumber NetNumber)
+
+{
+ struct sockaddr_ipx* pAddr;
+
+ pAddr= (struct sockaddr_ipx*)Addr;
+
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ {
+ memcpy(NetNumber, pAddr->sa_netnum, sizeof(NetNumber));
+
+ return osl_Socket_Ok;
+ }
+ else
+ return osl_Socket_Error;
+}
+
+
+/*****************************************************************************/
+/* osl_getIpxNodeNumber */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getIpxNodeNumber(oslSocketAddr Addr,
+ oslSocketIpxNodeNumber NodeNumber)
+
+{
+ struct sockaddr_ipx* pAddr;
+
+ pAddr= (struct sockaddr_ipx*)Addr;
+
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ {
+ memcpy(NodeNumber, pAddr->sa_nodenum, sizeof(NodeNumber));
+
+ return osl_Socket_Ok;
+ }
+ else
+ return osl_Socket_Error;
+}
+
+
+/*****************************************************************************/
+/* osl_getIpxSocketNumber */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getIpxSocketNumber(oslSocketAddr Addr)
+{
+ struct sockaddr_ipx* pAddr= (struct sockaddr_ipx*)Addr;
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ return pAddr->sa_socket;
+ else
+ return OSL_INVALID_IPX_SOCKET_NO;
+}
+
+#endif /* OBSOLETE */
+
+/*****************************************************************************/
+/* osl_createSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_createSocket(oslAddrFamily Family,
+ oslSocketType Type,
+ oslProtocol Protocol)
+{
+ int Flags;
+ oslSocket pSocket;
+
+ /* alloc memory */
+ pSocket= __osl_createSocketImpl(OSL_INVALID_SOCKET);
+
+ /* 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_TRACE("osl_createSocket failed. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+
+ __osl_destroySocketImpl((pSocket));
+ pSocket= 0;
+ }
+ else
+ {
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ if (fcntl(pSocket->m_Socket, F_SETFD, Flags) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_createSocket failed changing socket flags. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+ }
+ }
+ else
+ {
+ pSocket->m_nLastError=errno;
+ }
+
+
+ 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) ) )
+ {
+#if defined(LINUX)
+ if ( pSocket->m_bIsAccepting == sal_True )
+ {
+ OSL_ENSURE(0, "osl_destroySocket : attempt to destroy socket while accepting\n");
+ return;
+ }
+#endif /* LINUX */
+ osl_closeSocket( pSocket );
+ __osl_destroySocketImpl( pSocket );
+ }
+}
+
+
+
+/*****************************************************************************/
+/* osl_closeSocket */
+/*****************************************************************************/
+void SAL_CALL osl_closeSocket(oslSocket pSocket)
+{
+ int nRet;
+ int nFD;
+
+ /* socket already invalid */
+ if(pSocket==0)
+ return;
+
+ pSocket->m_nLastError=0;
+ nFD = pSocket->m_Socket;
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+
+#if defined(LINUX)
+ pSocket->m_bIsInShutdown = sal_True;
+
+ if ( pSocket->m_bIsAccepting == sal_True )
+ {
+ int nConnFD;
+ struct sockaddr aSockAddr;
+ socklen_t nSockLen = sizeof(aSockAddr);
+
+ nRet = getsockname(nFD, &aSockAddr, &nSockLen);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("getsockname");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ if ( aSockAddr.sa_family == AF_INET )
+ {
+ struct sockaddr_in* pSockAddrIn = (struct sockaddr_in*) &aSockAddr;
+
+ if ( pSockAddrIn->sin_addr.s_addr == htonl(INADDR_ANY) )
+ {
+ pSockAddrIn->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+
+ nConnFD = socket(AF_INET, SOCK_STREAM, 0);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nConnFD < 0 )
+ {
+ perror("socket");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ nRet = connect(nConnFD, &aSockAddr, sizeof(aSockAddr));
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("connect");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+ close(nConnFD);
+ }
+ }
+#endif /* LINUX */
+
+ /* registrierten Callback ausfuehren */
+ if (pSocket->m_CloseCallback != NULL)
+ {
+ pSocket->m_CloseCallback(pSocket->m_CallbackArg);
+ }
+
+ nRet=close(nFD);
+ if ( nRet != 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("closeSocket close error '%s'\n",strerror(errno));
+ }
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+}
+
+/*****************************************************************************/
+/* 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)
+{
+#if defined(LINUX) || defined(FREEBSD)
+ socklen_t AddrLen;
+#else
+ /* mfe: Solaris 'cc +w' means Addrlen should be signed! */
+ /* it's really defined as 'int*' in /usr/include/sys/socket.h! */
+ /* the man page says it expects a 'size_t' */
+ int AddrLen;
+#endif
+ struct sockaddr Addr;
+ oslSocketAddr pAddr;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getsockname(pSocket->m_Socket, &Addr, PTR_SIZE_T(AddrLen)) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_getPeerAddrOfSocket */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
+{
+ sal_uInt32 AddrLen;
+ struct sockaddr Addr;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return 0;
+ }
+
+ pSocket->m_nLastError=0;
+ AddrLen= sizeof(struct sockaddr);
+
+ if(getpeername(pSocket->m_Socket, &Addr, (int*)PTR_SIZE_T(AddrLen)) == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return 0;
+ }
+ return __osl_createSocketAddrFromSystem( &Addr );
+}
+
+/*****************************************************************************/
+/* osl_bindAddrToSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
+ oslSocketAddr pAddr)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket && pAddr );
+ if ( pSocket == 0 || pAddr == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
+
+ if ( nRet == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+
+/*****************************************************************************/
+/* osl_listenOnSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
+ sal_Int32 MaxPendingConnections)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = listen(pSocket->m_Socket,
+ MaxPendingConnections == -1 ?
+ SOMAXCONN :
+ MaxPendingConnections);
+ if ( nRet == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+
+/*****************************************************************************/
+/* osl_connectSocketTo */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
+ oslSocketAddr pAddr,
+ const TimeValue* pTimeout)
+{
+ fd_set WriteSet;
+ fd_set ExcptSet;
+ int ReadyHandles;
+ struct timeval tv;
+ oslSocketResult Result= osl_Socket_Ok;
+
+ OSL_PRECOND(pSocket, "osl_connectSocketTo(): need a valid socket!\n");
+
+ if ( pSocket == 0 )
+ {
+ return osl_Socket_Error;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if (osl_isNonBlockingMode(pSocket))
+ {
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ return osl_Socket_Ok;
+ else
+ if (errno == EWOULDBLOCK || errno == EINPROGRESS)
+ {
+ pSocket->m_nLastError=EINPROGRESS;
+ return osl_Socket_InProgress;
+ }
+
+
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("can't connect : '%s'",strerror(errno));
+ return osl_Socket_Error;
+ }
+
+ /* set socket temporarily to non-blocking */
+ OSL_VERIFY(osl_enableNonBlockingMode(pSocket, sal_True));
+
+ /* initiate connect */
+ if(connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ {
+ /* immediate connection */
+ osl_enableNonBlockingMode(pSocket, sal_False);
+
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ /* really an error or just delayed? */
+ if (errno != EINPROGRESS)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE(
+ "osl_connectSocketTo(): connect failed: errno: %d (%s)\n",
+ errno, strerror(errno));
+
+ osl_enableNonBlockingMode(pSocket, sal_False);
+ return osl_Socket_Error;
+ }
+ }
+
+
+ /* prepare select set for socket */
+ FD_ZERO(&WriteSet);
+ FD_ZERO(&ExcptSet);
+ FD_SET(pSocket->m_Socket, &WriteSet);
+ FD_SET(pSocket->m_Socket, &ExcptSet);
+
+ /* prepare timeout */
+ if (pTimeout)
+ {
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec= pTimeout->Seconds;
+ tv.tv_usec= pTimeout->Nanosec / 1000L;
+ }
+
+ /* select */
+ ReadyHandles= select(pSocket->m_Socket+1,
+ 0,
+ PTR_FD_SET(WriteSet),
+ PTR_FD_SET(ExcptSet),
+ (pTimeout) ? &tv : 0);
+
+ if (ReadyHandles > 0) /* connected */
+ {
+ if ( FD_ISSET(pSocket->m_Socket, &WriteSet ) )
+ {
+ int nErrorCode = 0;
+#ifdef SOLARIS
+/* mfe: Solaris 'cc +w' means 5th argument should be a 'int*'!
+ it's really defined as 'int*' in /usr/include/sys/socket.h!
+ the man page says it expects a 'size_t*'
+*/
+ int nErrorSize = sizeof( nErrorCode );
+#else
+ size_t nErrorSize = sizeof( nErrorCode );
+#endif
+
+ int nSockOpt;
+
+ nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
+#ifdef SOLARIS
+/* mfe: Solaris 'cc +w' means 4th argument should be a 'char*'!
+ it's really defined as 'char*' in /usr/include/sys/socket.h!
+ the man page says it expects a 'void*'
+*/
+ (char*)
+#endif
+ &nErrorCode, (int*)&nErrorSize );
+ if ( (nSockOpt == 0) && (nErrorCode == 0))
+ Result = osl_Socket_Ok;
+ else
+ Result = osl_Socket_Error;
+ }
+ else
+ {
+ Result= osl_Socket_Error;
+ }
+ }
+ else if (ReadyHandles < 0) /* error */
+ {
+ if (errno == EBADF) /* most probably interrupted by close() */
+ {
+ /* do not access pSockImpl because it is about to be or */
+ /* already destroyed */
+ return osl_Socket_Interrupted;
+ }
+ else
+ {
+ pSocket->m_nLastError=errno;
+ Result= osl_Socket_Error;
+ }
+ }
+ else /* timeout */
+ {
+ pSocket->m_nLastError=errno;
+ Result= osl_Socket_TimedOut;
+ }
+
+ osl_enableNonBlockingMode(pSocket, sal_False);
+
+ return Result;
+}
+
+
+/*****************************************************************************/
+/* osl_acceptConnectionOnSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
+ oslSocketAddr* ppAddr)
+{
+ struct sockaddr Addr;
+ int Connection, Flags;
+ sal_uInt32 AddrLen = sizeof(struct sockaddr);
+ oslSocket pConnectionSockImpl;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return 0;
+ }
+
+ pSocket->m_nLastError=0;
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_True;
+#endif /* LINUX */
+
+ if( ppAddr && *ppAddr )
+ {
+ osl_destroySocketAddr( *ppAddr );
+ *ppAddr = 0;
+ }
+
+ /* prevent Linux EINTR behaviour */
+ do
+ {
+ Connection = accept(pSocket->m_Socket, &Addr, (int*)PTR_SIZE_T(AddrLen));
+ } while (Connection == -1 && errno == EINTR);
+
+
+ /* accept failed? */
+ if( Connection == OSL_SOCKET_ERROR )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_acceptConnectionOnSocket : accept error '%s'\n",strerror(errno));
+
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_False;
+#endif /* LINUX */
+ return 0;
+ }
+
+ OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
+
+
+#if defined(LINUX)
+ if ( pSocket->m_bIsInShutdown == sal_True )
+ {
+ close(Connection);
+ OSL_TRACE("osl_acceptConnectionOnSocket : close while accept\n");
+ return 0;
+ }
+#endif /* LINUX */
+
+
+ if(ppAddr)
+ {
+ *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
+ }
+
+ /* alloc memory */
+ pConnectionSockImpl= __osl_createSocketImpl(OSL_INVALID_SOCKET);
+
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ if (fcntl(Connection, F_SETFD, Flags) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_acceptConnectionOnSocket failed changing socket flags. Errno: %d (%s)\n",
+ errno,
+ strerror(errno));
+ }
+
+ }
+
+ pConnectionSockImpl->m_Socket = Connection;
+ pConnectionSockImpl->m_nLastError = 0;
+ pConnectionSockImpl->m_CloseCallback = NULL;
+ pConnectionSockImpl->m_CallbackArg = NULL;
+#if defined(LINUX)
+ pConnectionSockImpl->m_bIsAccepting = sal_False;
+
+ pSocket->m_bIsAccepting = sal_False;
+#endif /* LINUX */
+ return pConnectionSockImpl;
+}
+
+/*****************************************************************************/
+/* osl_receiveSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
+ void* pBuffer,
+ sal_uInt32 BytesToRead,
+ oslSocketMsgFlag Flag)
+{
+ int nRead;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ do
+ {
+ nRead = recv(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToRead,
+ MSG_FLAG_TO_NATIVE(Flag));
+ } while ( nRead < 0 && errno == EINTR );
+
+ if ( nRead < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,strerror(errno));
+ }
+ else if ( nRead == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
+ }
+
+ return nRead;
+}
+
+
+/*****************************************************************************/
+/* osl_receiveFromSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
+ oslSocketAddr pSenderAddr,
+ void* pBuffer,
+ sal_uInt32 BufferSize,
+ oslSocketMsgFlag Flag)
+{
+ int nRead;
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( pSenderAddr )
+ {
+ AddrLen = sizeof( struct sockaddr );
+ pSystemSockAddr = &(pSenderAddr->m_sockaddr);
+ }
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_receiveFromSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRead = recvfrom(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BufferSize,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ PTR_SIZE_T(AddrLen));
+
+ if ( nRead < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_receiveFromSocket failed : %i '%s'",nRead,strerror(errno));
+ }
+ else if ( nRead == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
+ }
+
+ return nRead;
+}
+
+
+/*****************************************************************************/
+/* osl_sendSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ int nWritten;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_sendSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ do
+ {
+ nWritten = send(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag));
+ } while ( nWritten < 0 && errno == EINTR );
+
+
+ if ( nWritten < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,strerror(errno));
+ }
+ else if ( nWritten == 0 )
+ {
+ OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,"EOL");
+ }
+
+ return nWritten;
+}
+
+/*****************************************************************************/
+/* osl_sendToSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
+ oslSocketAddr ReceiverAddr,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ int nWritten;
+
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( ReceiverAddr )
+ {
+ pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
+ AddrLen = sizeof( struct sockaddr );
+ }
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_sendToSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ /* ReceiverAddr might be 0 when used on a connected socket. */
+ /* Then sendto should behave like send. */
+
+ nWritten = sendto(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ AddrLen);
+
+ if ( nWritten < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,strerror(errno));
+ }
+ else if ( nWritten == 0 )
+ {
+ OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,"EOL");
+ }
+
+ return nWritten;
+}
+
+/*****************************************************************************/
+/* osl_readSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_readSocket (
+ oslSocket pSocket, void *pBuffer, sal_Int32 n )
+{
+ sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
+ sal_uInt32 BytesRead= 0;
+ sal_uInt32 BytesToRead= n;
+
+ OSL_ASSERT( pSocket);
+
+ /* loop until all desired bytes were read or an error occured */
+ 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 )
+{
+ /* 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;
+
+ OSL_ASSERT( pSocket );
+
+ 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_socket_poll */
+/*****************************************************************************/
+
+#ifdef HAVE_POLL_H /* poll() */
+
+sal_Bool __osl_socket_poll (
+ oslSocket pSocket,
+ const TimeValue* pTimeout,
+ short nEvent)
+{
+ struct pollfd fds;
+ int timeout;
+ int result;
+
+ OSL_ASSERT(pSocket);
+ pSocket->m_nLastError = 0;
+
+ fds.fd = pSocket->m_Socket;
+ fds.events = nEvent;
+ fds.revents = 0;
+
+ timeout = -1;
+ if (pTimeout)
+ {
+ /* Convert to [ms] */
+ timeout = pTimeout->Seconds * 1000;
+ timeout += pTimeout->Nanosec / (1000 * 1000);
+ }
+
+ result = poll (&fds, 1, timeout);
+ if (result < 0)
+ {
+ pSocket->m_nLastError = errno;
+ OSL_TRACE("__osl_socket_poll(): poll error: %d (%s)",
+ errno, strerror(errno));
+ return sal_False;
+ }
+ if (result == 0)
+ {
+ /* Timeout */
+ return sal_False;
+ }
+
+ return ((fds.revents & nEvent) == nEvent);
+}
+
+#else /* select() */
+
+sal_Bool __osl_socket_poll (
+ oslSocket pSocket,
+ const TimeValue* pTimeout,
+ short nEvent)
+{
+ fd_set fds;
+ struct timeval tv;
+ int result;
+
+ OSL_ASSERT(pSocket);
+ pSocket->m_nLastError = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ /* Convert to 'timeval' */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000;
+ }
+
+ result = select (
+ pSocket->m_Socket + 1,
+ (nEvent == POLLIN ) ? PTR_FD_SET(fds) : NULL,
+ (nEvent == POLLOUT) ? PTR_FD_SET(fds) : NULL,
+ (nEvent == POLLPRI) ? PTR_FD_SET(fds) : NULL,
+ (pTimeout) ? &tv : NULL);
+
+ if (result < 0)
+ {
+ pSocket->m_nLastError = errno;
+ OSL_TRACE("__osl_socket_poll(): select error: %d (%s)",
+ errno, strerror(errno));
+ return sal_False;
+ }
+ if (result == 0)
+ {
+ /* Timeout */
+ return sal_False;
+ }
+
+ return (FD_ISSET(pSocket->m_Socket, &fds) ? sal_True : sal_False);
+}
+
+#endif /* HAVE_POLL_H */
+
+/*****************************************************************************/
+/* osl_isReceiveReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isReceiveReady (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLIN);
+}
+
+/*****************************************************************************/
+/* osl_isSendReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isSendReady (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLOUT);
+}
+
+/*****************************************************************************/
+/* osl_isExceptionPending */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isExceptionPending (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLPRI);
+}
+
+/*****************************************************************************/
+/* osl_shutdownSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
+ oslSocketDirection Direction)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
+ if (nRet != 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("shutdown error '%s'\n",strerror(errno));
+ }
+ return (nRet==0);
+}
+
+
+/*****************************************************************************/
+/* osl_getSocketOption */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ (int*)PTR_SIZE_T(BufferLen)) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ return -1;
+ }
+
+ return BufferLen;
+}
+
+/*****************************************************************************/
+/* osl_setSocketOption */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = setsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ BufferLen);
+
+ if ( nRet < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_enableNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
+ sal_Bool On)
+{
+ int flags;
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
+
+ if (On)
+ flags |= O_NONBLOCK;
+ else
+ flags &= ~(O_NONBLOCK);
+
+ nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
+
+ if ( nRet < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_isNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
+{
+ int flags;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
+
+ if (flags == -1 || !(flags & O_NONBLOCK))
+ return sal_False;
+ else
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getSocketType */
+/*****************************************************************************/
+oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
+{
+ int Type=0;
+ sal_uInt32 TypeSize= sizeof(Type);
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return osl_Socket_TypeInvalid;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
+ OPTION_TO_NATIVE(osl_Socket_OptionType),
+ (sal_Char*)&Type,
+ (int*)PTR_SIZE_T(TypeSize)) == -1)
+ {
+ /* error */
+ pSocket->m_nLastError=errno;
+ return osl_Socket_TypeInvalid;
+ }
+
+ return TYPE_FROM_NATIVE(Type);
+
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketErrorDescription */
+/*****************************************************************************/
+void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
+{
+ sal_Char pszError[1024];
+
+ pszError[0] = '\0';
+
+ osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
+
+ rtl_uString_newFromAscii(ustrError,pszError);
+
+ return;
+}
+
+
+void SAL_CALL osl_psz_getLastSocketErrorDescription(oslSocket pSocket, sal_Char* pBuffer, sal_uInt32 BufferSize)
+{
+ /* make shure pBuffer will be a zero-terminated string even when strncpy has to cut */
+ pBuffer[BufferSize-1]= '\0';
+
+ if ( pSocket == 0 )
+ {
+ strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
+ return;
+ }
+
+ strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
+ return;
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketError */
+/*****************************************************************************/
+oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
+{
+ if ( pSocket == 0 )
+ {
+ return ERROR_FROM_NATIVE(EINVAL);
+ }
+
+ return ERROR_FROM_NATIVE(pSocket->m_nLastError);
+}
+
+/*****************************************************************************/
+/* SocketSet */
+/*****************************************************************************/
+typedef struct _TSocketSetImpl
+{
+ int m_MaxHandle; /* for select(), the largest descriptor in the set */
+ fd_set m_Set; /* the set of descriptors */
+
+} TSocketSetImpl;
+
+/*****************************************************************************/
+/* osl_createSocketSet */
+/*****************************************************************************/
+oslSocketSet SAL_CALL osl_createSocketSet()
+{
+ TSocketSetImpl* pSet;
+
+ pSet= (TSocketSetImpl*)malloc(sizeof(TSocketSetImpl));
+
+ OSL_ASSERT(pSet);
+
+ if(pSet)
+ {
+ pSet->m_MaxHandle= 0;
+ FD_ZERO(&pSet->m_Set);
+ }
+
+ return (oslSocketSet)pSet;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketSet(oslSocketSet Set)
+{
+ if(Set)
+ free(Set);
+}
+
+/*****************************************************************************/
+/* osl_clearSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_clearSocketSet(oslSocketSet Set)
+{
+ TSocketSetImpl* pSet;
+ OSL_ASSERT(Set);
+ if ( Set == 0 )
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+ pSet->m_MaxHandle= 0;
+
+ FD_ZERO(&pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_addToSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_addToSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+
+ if ( Set == 0 || pSocket == 0)
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ /* correct max handle */
+ if(pSocket->m_Socket > pSet->m_MaxHandle)
+ pSet->m_MaxHandle= pSocket->m_Socket;
+ FD_SET(pSocket->m_Socket, &pSet->m_Set);
+
+}
+
+/*****************************************************************************/
+/* osl_removeFromSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_removeFromSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+
+ if ( Set == 0 || pSocket == 0)
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ /* correct max handle */
+ if(pSocket->m_Socket == pSet->m_MaxHandle)
+ {
+ /* not optimal, since the next used descriptor might be */
+ /* much smaller than m_Socket-1, but it will do */
+ pSet->m_MaxHandle--;
+ if(pSet->m_MaxHandle < 0)
+ {
+ pSet->m_MaxHandle= 0; /* avoid underflow */
+ }
+ }
+
+ FD_CLR(pSocket->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_isInSocketSet */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isInSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+ if ( Set == 0 || pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ return (FD_ISSET(pSocket->m_Socket, &pSet->m_Set) != 0);
+}
+
+/*****************************************************************************/
+/* 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)
+ {
+ /* non-blocking call */
+ 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;
+
+ /* get max handle from all sets */
+ if (pInSet)
+ MaxHandle= pInSet->m_MaxHandle;
+
+ if (pOutSet && (pOutSet->m_MaxHandle > MaxHandle))
+ MaxHandle= pOutSet->m_MaxHandle;
+
+ if (pOOBSet && (pOOBSet->m_MaxHandle > MaxHandle))
+ MaxHandle= pOOBSet->m_MaxHandle;
+
+ return select(MaxHandle+1,
+ pInSet ? PTR_FD_SET(pInSet->m_Set) : 0,
+ pOutSet ? PTR_FD_SET(pOutSet->m_Set) : 0,
+ pOOBSet ? PTR_FD_SET(pOOBSet->m_Set) : 0,
+ pTimeout ? &tv : 0);
+}
+