84cb130b0f
2008/04/01 12:34:09 thb 1.28.116.2: #i85898# Stripping all external header guards 2008/03/31 13:23:44 rt 1.28.116.1: #i87441# Change license header to LPGL v3.
3066 lines
87 KiB
C
3066 lines
87 KiB
C
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: socket.c,v $
|
|
* $Revision: 1.29 $
|
|
*
|
|
* 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 (IRIX) || defined(NETBSD) || defined ( FREEBSD )
|
|
#include <sys/poll.h>
|
|
#define HAVE_POLL_H
|
|
#endif /* HAVE_POLL_H */
|
|
|
|
#if defined(SOLARIS)
|
|
#include <poll.h>
|
|
#define HAVE_POLL_H
|
|
#endif /* SOLARIS */
|
|
|
|
#if defined(MACOSX)
|
|
/* Include our own poll.h because OS X doesn't implement one */
|
|
#include "poll.h"
|
|
#define HAVE_POLL_H
|
|
#endif
|
|
|
|
#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)
|
|
{
|
|
#if defined(LINUX) || (defined(FREEBSD) && (__FreeBSD_version >= 601103))
|
|
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]);
|
|
|
|
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]);
|
|
}
|
|
}
|
|
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;
|
|
|
|
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;
|
|
|
|
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 ((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 /* 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)
|
|
{
|
|
socklen_t AddrLen;
|
|
struct sockaddr Addr;
|
|
oslSocketAddr pAddr;
|
|
|
|
if (pSocket == NULL) /* ENOTSOCK */
|
|
return ((oslSocketAddr)NULL);
|
|
|
|
AddrLen= sizeof(struct sockaddr);
|
|
|
|
if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
|
|
return ((oslSocketAddr)NULL);
|
|
|
|
pAddr = __osl_createSocketAddrFromSystem( &Addr );
|
|
return pAddr;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* osl_getPeerAddrOfSocket */
|
|
/*****************************************************************************/
|
|
oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
|
|
{
|
|
socklen_t 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, &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;
|
|
socklen_t nErrorSize = sizeof( nErrorCode );
|
|
|
|
int nSockOpt;
|
|
|
|
nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
|
|
&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;
|
|
oslSocket pConnectionSockImpl;
|
|
|
|
socklen_t AddrLen = sizeof(struct sockaddr);
|
|
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, &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;
|
|
socklen_t 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,
|
|
&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)
|
|
{
|
|
socklen_t nOptLen = (socklen_t) 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,
|
|
&nOptLen) == -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;
|
|
socklen_t 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,
|
|
&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);
|
|
}
|
|
|