diff options
author | Oliver Braun <obr@openoffice.org> | 2001-03-30 15:49:12 +0000 |
---|---|---|
committer | Oliver Braun <obr@openoffice.org> | 2001-03-30 15:49:12 +0000 |
commit | ebd00f5c46707e0dfcdd074f581ae86c0576e69b (patch) | |
tree | a67753ddf07ddce71eaf0be6c93da4ef8e06a839 /sal/osl/unx | |
parent | 1db2b85d03092679afaf90ec94d2fbd0ed5a83cc (diff) |
socket.cxx -> socket.c
Diffstat (limited to 'sal/osl/unx')
-rw-r--r-- | sal/osl/unx/socket.c | 3112 |
1 files changed, 3112 insertions, 0 deletions
diff --git a/sal/osl/unx/socket.c b/sal/osl/unx/socket.c new file mode 100644 index 000000000000..b3ceb994b7d9 --- /dev/null +++ b/sal/osl/unx/socket.c @@ -0,0 +1,3112 @@ +/************************************************************************* + * + * $RCSfile: socket.c,v $ + * + * $Revision: 1.10 $ + * + * last change: $Author: obr $ $Date: 2001-03-30 16:49:12 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#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> + + +#ifndef _SAL_TYPES_H_ +#include <sal/types.h> +#endif + +#include "sockimpl.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 + + +/*****************************************************************************/ +/* 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 */ +/*****************************************************************************/ + +#ifdef DEBUG +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 + + +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 + +#ifdef DEBUG + g_nSocketImpl ++; +#endif + return pSocket; +} + +void __osl_destroySocketImpl(oslSocket Socket) +{ + if ( Socket != NULL) + free((struct oslSocketImpl *) Socket); +#ifdef DEBUG + g_nSocketImpl --; +#endif +} + +static oslSocketAddr __osl_createSocketAddr( ) +{ + oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl )); +#ifdef DEBUG + 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 ) +{ +#ifdef DEBUG + 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, 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, 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 ; +#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 (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]); + + if (execvp ("/bin/domainname", argv) < 0) + { + 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]); + } + else + { + close (p[0]); + close (p[1]); + } + + waitpid (pid, &nStatus, 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[ 256 ]; + sal_Char pQualifiedHostBuffer[ 256 ]; + 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; + + sal_Char *cn; + + if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL)) + return ((oslHostAddr)NULL); + + 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); + } + + 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; + + strcpy(LocalHostname, uts.nodename); +#else /* BSD compatible */ + + if (gethostname(LocalHostname, sizeof(LocalHostname)) != 0) + return osl_Socket_Error; +#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 ((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 */ + + } + 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 +/*****************************************************************************/ +/* 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 + +/*****************************************************************************/ +/* 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; +} + +/*****************************************************************************/ +/* osl_copySocket */ +/*****************************************************************************/ +oslSocket SAL_CALL osl_copySocket(oslSocket pSocket) +{ + osl_acquireSocket( pSocket ); + 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 + osl_closeSocket( pSocket ); + __osl_destroySocketImpl( pSocket ); + } +} + + +/*****************************************************************************/ +/* osl_destroySocket */ +/*****************************************************************************/ +void SAL_CALL osl_destroySocket(oslSocket pSocket) +{ + osl_releaseSocket( 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 defined(DEBUG) + if ( nRet < 0 ) + { + perror("getsockname"); + } +#endif /* DEBUG */ + + 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 defined(DEBUG) + if ( nConnFD < 0 ) + { + perror("socket"); + } +#endif /* DEBUG */ + + nRet = connect(nConnFD, &aSockAddr, sizeof(aSockAddr)); +#if defined(DEBUG) + if ( nRet < 0 ) + { + perror("connect"); + } +#endif /* DEBUG */ + 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) +{ +#ifdef LINUX + 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, 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, &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 + + if( ppAddr && *ppAddr ) + { + osl_destroySocketAddr( *ppAddr ); + *ppAddr = 0; + } + + /* prevent Linux EINTR behaviour */ + do + { + Connection = accept(pSocket->m_Socket, &Addr, PTR_SIZE_T(AddrLen)); + } while (Connection == -1 && errno == EINTR); + + + /* accept failed? */ + if( Connection == OSL_SOCKET_ERROR ) + { + pSocket->m_nLastError=errno; + +#if defined(DEBUG) + fprintf(stderr,"osl_acceptConnectionOnSocket : accept error '%s'\n",strerror(errno)); +#endif + +#if defined(LINUX) + pSocket->m_bIsAccepting = sal_False; +#endif + return 0; + } + + OSL_ASSERT(AddrLen == sizeof(struct sockaddr)); + + +#if defined(LINUX) + if ( pSocket->m_bIsInShutdown == sal_True ) + { + close(Connection); +#if defined(DEBUG) + fprintf(stderr,"osl_acceptConnectionOnSocket : close while accept\n"); +#endif + return 0; + } +#endif + + + 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 + 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_isReceiveReady */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isReceiveReady(oslSocket pSocket, const TimeValue* pTimeout) +{ + fd_set fds; + struct timeval tv; + int result; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + FD_ZERO(&fds); + FD_SET(pSocket->m_Socket, &fds); + + if (pTimeout) + { + tv.tv_sec = pTimeout->Seconds; + tv.tv_usec = pTimeout->Nanosec / 1000L; + } + + result= select(pSocket->m_Socket+1, /* highest socketno to monitor */ + PTR_FD_SET(fds), /* check read operations */ + 0, /* check write ops */ + 0, /* ckeck for OOB */ + (pTimeout) ? &tv : 0); /* use timeout? */ + + if(result < 0) /* error */ + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_isReceiveReady(): select-error: %d (%s)\n", errno, strerror(errno)); + return sal_False; + } + + if(result == 0) /* timeout */ + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + + +/*****************************************************************************/ +/* osl_isSendReady */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isSendReady(oslSocket pSocket, const TimeValue* pTimeout) +{ + fd_set fds; + struct timeval tv; + int nRet; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + pSocket->m_nLastError=0; + + FD_ZERO(&fds); + FD_SET(pSocket->m_Socket, &fds); + + if (pTimeout) + { + tv.tv_sec = pTimeout->Seconds; + tv.tv_usec = pTimeout->Nanosec / 1000L; + } + + nRet = select(pSocket->m_Socket+1, /* highest socketno to monitor */ + 0, /* check read operations */ + PTR_FD_SET(fds), /* check write ops */ + 0, /* ckeck for OOB */ + (pTimeout) ? &tv : 0); /* use timeout? */ + + if ( nRet < 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_isSendReady(): select-error: %d (%s)\n", errno, strerror(errno)); + return sal_False; + } + + if( nRet == 0 ) + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + +/*****************************************************************************/ +/* osl_isExceptionPending */ +/*****************************************************************************/ +sal_Bool SAL_CALL osl_isExceptionPending(oslSocket pSocket, const TimeValue* pTimeout) +{ + fd_set fds; + struct timeval tv; + int nRet; + + OSL_ASSERT(pSocket); + if ( pSocket == 0 ) + { + return sal_False; + } + + pSocket->m_nLastError=0; + + FD_ZERO(&fds); + FD_SET(pSocket->m_Socket, &fds); + + if (pTimeout) + { + tv.tv_sec = pTimeout->Seconds; + tv.tv_usec = pTimeout->Nanosec / 1000L; + } + + nRet = select(pSocket->m_Socket+1, /* highest socketno to monitor */ + 0, /* check read operations */ + 0, /* check write ops */ + PTR_FD_SET(fds), /* ckeck for OOB */ + (pTimeout) ? &tv : 0); /* use timeout? */ + + if ( nRet < 0 ) + { + pSocket->m_nLastError=errno; + OSL_TRACE("osl_isExceptionPending(): select-error: %d (%s)\n", errno, strerror(errno)); + return sal_False; + } + + if( nRet == 0 ) + { + pSocket->m_nLastError=errno; + return sal_False; + } + + return sal_True; +} + +/*****************************************************************************/ +/* 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; +#ifdef DEBUG + fprintf(stderr,"shutdown error '%s'\n",strerror(errno)); +#endif + } + 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, + 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, + 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); +} + |