1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <osl/socket.h>
23 #include <osl/mutex.h>
24 #include <osl/signal.h>
26 #include <rtl/alloc.h>
27 #include <rtl/byteseq.h>
29 #include <sal/types.h>
30 #include <sal/log.hxx>
32 #include "sockimpl.hxx"
33 #include "unixerrnostring.hxx"
35 /* defines for poll */
40 #if defined(LINUX) || defined(NETBSD) || defined ( FREEBSD ) || \
41 defined (MACOSX) || defined (OPENBSD) || defined(DRAGONFLY)
44 #endif /* HAVE_POLL_H */
53 #define POLLOUT 0x0002
54 #define POLLPRI 0x0004
55 #endif /* HAVE_POLL_H */
57 /* defines for shutdown */
63 oslSocketAddr is a pointer to a Berkeley struct sockaddr.
64 I refrained from using sockaddr_in because of possible further
65 extensions of this socket-interface (IP-NG?).
66 The intention was to hide all Berkeley data-structures from
67 direct access past the osl-interface.
69 The current implementation is internet (IP) centered. All
70 the constructor-functions (osl_create...) take parameters
71 that will probably make sense only in the IP-environment
72 (e.g. because of using the dotted-address-format).
74 If the interface will be extended to host other protocol-
75 families, I expect no externally visible changes in the
76 existing functions. You'll probably need only new
77 constructor-functions who take the different address
78 formats into consideration (maybe a long dotted address
82 /* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */
83 /* are the same! I don't like it very much but see no other easy way to */
84 /* conceal the struct sockaddr from the eyes of the user. */
86 #define OSL_INVALID_SOCKET -1
87 #define OSL_SOCKET_ERROR -1
89 /* Buffer size for gethostbyname */
90 #define MAX_HOSTBUFFER_SIZE 2048
92 static const unsigned long FamilyMap
[]= {
93 AF_INET
, /* osl_Socket_FamilyInet */
94 AF_IPX
, /* osl_Socket_FamilyIpx */
95 0 /* osl_Socket_FamilyInvalid */
98 static oslAddrFamily
osl_AddrFamilyFromNative(sal_uInt32 nativeType
)
100 oslAddrFamily i
= oslAddrFamily(0);
102 while(i
!= osl_Socket_FamilyInvalid
)
104 if(FamilyMap
[i
] == nativeType
)
106 i
= static_cast<oslAddrFamily
>( i
+ 1 );
112 #define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
113 #define FAMILY_TO_NATIVE(x) static_cast<short>(FamilyMap[x])
115 static const sal_uInt32 ProtocolMap
[]= {
116 0, /* osl_Socket_ProtocolIp */
117 NSPROTO_IPX
, /* osl_Socket_ProtocolIpx */
118 NSPROTO_SPX
, /* osl_Socket_ProtocolSpx */
119 NSPROTO_SPXII
, /* osl_Socket_ProtocolSpxII */
120 0 /* osl_Socket_ProtocolInvalid */
123 #define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
125 static const sal_uInt32 TypeMap
[]= {
126 SOCK_STREAM
, /* osl_Socket_TypeStream */
127 SOCK_DGRAM
, /* osl_Socket_TypeDgram */
128 SOCK_RAW
, /* osl_Socket_TypeRaw */
129 SOCK_RDM
, /* osl_Socket_TypeRdm */
130 SOCK_SEQPACKET
, /* osl_Socket_TypeSeqPacket */
131 0 /* osl_Socket_TypeInvalid */
134 static oslSocketType
osl_SocketTypeFromNative(sal_uInt32 nativeType
)
136 oslSocketType i
= oslSocketType(0);
138 while(i
!= osl_Socket_TypeInvalid
)
140 if(TypeMap
[i
] == nativeType
)
142 i
= static_cast<oslSocketType
>(i
+ 1);
148 #define TYPE_TO_NATIVE(x) TypeMap[x]
149 #define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
151 static const sal_uInt32 OptionMap
[]= {
152 SO_DEBUG
, /* osl_Socket_OptionDebug */
153 SO_ACCEPTCONN
, /* osl_Socket_OptionAcceptConn */
154 SO_REUSEADDR
, /* osl_Socket_OptionReuseAddr */
155 SO_KEEPALIVE
, /* osl_Socket_OptionKeepAlive */
156 SO_DONTROUTE
, /* osl_Socket_OptionDontRoute */
157 SO_BROADCAST
, /* osl_Socket_OptionBroadcast */
158 SO_USELOOPBACK
, /* osl_Socket_OptionUseLoopback */
159 SO_LINGER
, /* osl_Socket_OptionLinger */
160 SO_OOBINLINE
, /* osl_Socket_OptionOOBinLine */
161 SO_SNDBUF
, /* osl_Socket_OptionSndBuf */
162 SO_RCVBUF
, /* osl_Socket_OptionRcvBuf */
163 SO_SNDLOWAT
, /* osl_Socket_OptionSndLowat */
164 SO_RCVLOWAT
, /* osl_Socket_OptionRcvLowat */
165 SO_SNDTIMEO
, /* osl_Socket_OptionSndTimeo */
166 SO_RCVTIMEO
, /* osl_Socket_OptionRcvTimeo */
167 SO_ERROR
, /* osl_Socket_OptionError */
168 SO_TYPE
, /* osl_Socket_OptionType */
169 TCP_NODELAY
, /* osl_Socket_OptionTcpNoDelay */
170 0 /* osl_Socket_OptionInvalid */
173 #define OPTION_TO_NATIVE(x) OptionMap[x]
175 static const sal_uInt32 OptionLevelMap
[]= {
176 SOL_SOCKET
, /* osl_Socket_LevelSocket */
177 IPPROTO_TCP
, /* osl_Socket_LevelTcp */
178 0 /* osl_Socket_LevelInvalid */
181 #define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
183 static const sal_uInt32 SocketMsgFlagMap
[]= {
184 0, /* osl_Socket_MsgNormal */
185 MSG_OOB
, /* osl_Socket_MsgOOB */
186 MSG_PEEK
, /* osl_Socket_MsgPeek */
187 MSG_DONTROUTE
, /* osl_Socket_MsgDontRoute */
188 MSG_MAXIOVLEN
, /* osl_Socket_MsgMaxIOVLen */
189 0 /* osl_Socket_MsgInvalid */
192 #define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
194 static const sal_uInt32 SocketDirection
[]= {
195 SD_RECEIVE
, /* osl_Socket_DirRead */
196 SD_SEND
, /* osl_Socket_DirWrite */
197 SD_BOTH
, /* osl_Socket_DirReadWrite */
198 0 /* osl_Socket_DirInvalid */
201 #define DIRECTION_TO_NATIVE(x) SocketDirection[x]
206 oslSocketError
const error
;
208 { 0, osl_Socket_E_None
}, /* no error */
209 { ENOTSOCK
, osl_Socket_E_NotSocket
}, /* Socket operation on non-socket */
210 { EDESTADDRREQ
, osl_Socket_E_DestAddrReq
}, /* Destination address required */
211 { EMSGSIZE
, osl_Socket_E_MsgSize
}, /* Message too long */
212 { EPROTOTYPE
, osl_Socket_E_Prototype
}, /* Protocol wrong type for socket */
213 { ENOPROTOOPT
, osl_Socket_E_NoProtocol
}, /* Protocol not available */
214 { EPROTONOSUPPORT
, osl_Socket_E_ProtocolNoSupport
}, /* Protocol not supported */
215 #ifdef ESOCKTNOSUPPORT
216 { ESOCKTNOSUPPORT
, osl_Socket_E_TypeNoSupport
}, /* Socket type not supported */
218 { EOPNOTSUPP
, osl_Socket_E_OpNotSupport
}, /* Operation not supported on socket */
219 { EPFNOSUPPORT
, osl_Socket_E_PfNoSupport
}, /* Protocol family not supported */
220 { EAFNOSUPPORT
, osl_Socket_E_AfNoSupport
}, /* Address family not supported by
222 { EADDRINUSE
, osl_Socket_E_AddrInUse
}, /* Address already in use */
223 { EADDRNOTAVAIL
, osl_Socket_E_AddrNotAvail
}, /* Can't assign requested address */
224 { ENETDOWN
, osl_Socket_E_NetDown
}, /* Network is down */
225 { ENETUNREACH
, osl_Socket_E_NetUnreachable
}, /* Network is unreachable */
226 { ENETRESET
, osl_Socket_E_NetReset
}, /* Network dropped connection because
228 { ECONNABORTED
, osl_Socket_E_ConnAborted
}, /* Software caused connection abort */
229 { ECONNRESET
, osl_Socket_E_ConnReset
}, /* Connection reset by peer */
230 { ENOBUFS
, osl_Socket_E_NoBufferSpace
}, /* No buffer space available */
231 { EISCONN
, osl_Socket_E_IsConnected
}, /* Socket is already connected */
232 { ENOTCONN
, osl_Socket_E_NotConnected
}, /* Socket is not connected */
233 { ESHUTDOWN
, osl_Socket_E_Shutdown
}, /* Can't send after socket shutdown */
235 { ETOOMANYREFS
, osl_Socket_E_TooManyRefs
}, /* Too many references: can't splice */
237 { ETIMEDOUT
, osl_Socket_E_TimedOut
}, /* Connection timed out */
238 { ECONNREFUSED
, osl_Socket_E_ConnRefused
}, /* Connection refused */
239 { EHOSTDOWN
, osl_Socket_E_HostDown
}, /* Host is down */
240 { EHOSTUNREACH
, osl_Socket_E_HostUnreachable
}, /* No route to host */
241 { EWOULDBLOCK
, osl_Socket_E_WouldBlock
}, /* call would block on non-blocking socket */
242 { EALREADY
, osl_Socket_E_Already
}, /* operation already in progress */
243 { EINPROGRESS
, osl_Socket_E_InProgress
}, /* operation now in progress */
244 { EAGAIN
, osl_Socket_E_WouldBlock
}, /* same as EWOULDBLOCK */
245 { -1, osl_Socket_E_InvalidError
}
248 static oslSocketError
osl_SocketErrorFromNative(int nativeType
)
252 while ((SocketError
[i
].error
!= osl_Socket_E_InvalidError
) &&
253 (SocketError
[i
].errcode
!= nativeType
)) i
++;
255 return SocketError
[i
].error
;
258 #define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
260 static oslSocketAddr
osl_psz_createInetSocketAddr (
261 const sal_Char
* pszDottedAddr
, sal_Int32 Port
);
263 static oslHostAddr
osl_psz_createHostAddr (
264 const sal_Char
*pszHostname
, const oslSocketAddr Addr
);
266 static oslHostAddr
osl_psz_createHostAddrByName (
267 const sal_Char
*pszHostname
);
269 static const sal_Char
* osl_psz_getHostnameOfHostAddr (
270 const oslHostAddr Addr
);
272 static oslSocketResult
osl_psz_getLocalHostname (
273 sal_Char
*pBuffer
, sal_uInt32 nBufLen
);
275 static oslSocketAddr
osl_psz_resolveHostname (
276 const sal_Char
* pszHostname
);
278 static sal_Int32
osl_psz_getServicePort (
279 const sal_Char
* pszServicename
, const sal_Char
* pszProtocol
);
281 static oslSocketResult
osl_psz_getHostnameOfSocketAddr (
282 oslSocketAddr Addr
, sal_Char
*pBuffer
, sal_uInt32 BufferSize
);
284 static oslSocketResult
osl_psz_getDottedInetAddrOfSocketAddr (
285 oslSocketAddr Addr
, sal_Char
*pBuffer
, sal_uInt32 BufferSize
);
287 static void osl_psz_getLastSocketErrorDescription (
288 oslSocket Socket
, sal_Char
* pBuffer
, sal_uInt32 BufferSize
);
290 static oslSocket
createSocketImpl(int Socket
)
294 pSocket
= static_cast<oslSocket
>(calloc(1, sizeof(struct oslSocketImpl
)));
296 pSocket
->m_Socket
= Socket
;
297 pSocket
->m_nLastError
= 0;
298 pSocket
->m_nRefCount
= 1;
300 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
301 pSocket
->m_bIsAccepting
= false;
307 static void destroySocketImpl(oslSocket Socket
)
309 if ( Socket
!= nullptr)
313 static oslSocketAddr
createSocketAddr()
315 oslSocketAddr pAddr
= static_cast<oslSocketAddr
>(rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl
)));
319 static oslSocketAddr
createSocketAddrWithFamily(
320 oslAddrFamily family
, sal_Int32 port
, sal_uInt32 nAddr
)
324 SAL_WARN_IF( family
!= osl_Socket_FamilyInet
, "sal.osl", "creating socket for non-IP address family" );
326 pAddr
= createSocketAddr();
329 case osl_Socket_FamilyInet
:
331 struct sockaddr_in
* pInetAddr
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
333 pInetAddr
->sin_family
= FAMILY_TO_NATIVE(osl_Socket_FamilyInet
);
334 pInetAddr
->sin_addr
.s_addr
= nAddr
;
335 pInetAddr
->sin_port
= static_cast<sal_uInt16
>(port
&0xffff);
339 pAddr
->m_sockaddr
.sa_family
= FAMILY_TO_NATIVE(family
);
344 static oslSocketAddr
createSocketAddrFromSystem( struct sockaddr
*pSystemSockAddr
)
346 oslSocketAddr pAddr
= createSocketAddr();
347 memcpy( &(pAddr
->m_sockaddr
), pSystemSockAddr
, sizeof( struct sockaddr
) );
351 static void destroySocketAddr( oslSocketAddr addr
)
356 oslSocketAddr SAL_CALL
osl_createEmptySocketAddr(oslAddrFamily Family
)
358 oslSocketAddr pAddr
= nullptr;
360 /* is it an internet-Addr? */
361 if (Family
== osl_Socket_FamilyInet
)
363 pAddr
= createSocketAddrWithFamily(Family
, 0 , htonl(INADDR_ANY
) );
367 pAddr
= createSocketAddrWithFamily( Family
, 0 , 0 );
373 oslSocketAddr SAL_CALL
osl_copySocketAddr(oslSocketAddr Addr
)
375 oslSocketAddr pCopy
= nullptr;
378 pCopy
= createSocketAddr();
381 memcpy(&(pCopy
->m_sockaddr
),&(Addr
->m_sockaddr
), sizeof(struct sockaddr
));
386 sal_Bool SAL_CALL
osl_isEqualSocketAddr (
390 struct sockaddr
* pAddr1
= nullptr;
391 struct sockaddr
* pAddr2
= nullptr;
393 assert(Addr1
&& Addr2
);
394 pAddr1
= &(Addr1
->m_sockaddr
);
395 pAddr2
= &(Addr2
->m_sockaddr
);
397 if (pAddr1
== pAddr2
)
402 if (pAddr1
->sa_family
== pAddr2
->sa_family
)
404 switch (pAddr1
->sa_family
)
408 struct sockaddr_in
* pInetAddr1
= reinterpret_cast<sockaddr_in
*>(pAddr1
);
409 struct sockaddr_in
* pInetAddr2
= reinterpret_cast<sockaddr_in
*>(pAddr2
);
411 if ((pInetAddr1
->sin_family
== pInetAddr2
->sin_family
) &&
412 (pInetAddr1
->sin_addr
.s_addr
== pInetAddr2
->sin_addr
.s_addr
) &&
413 (pInetAddr1
->sin_port
== pInetAddr2
->sin_port
))
420 return (memcmp(pAddr1
, pAddr2
, sizeof(struct sockaddr
)) == 0);
428 oslSocketAddr SAL_CALL
osl_createInetBroadcastAddr (
429 rtl_uString
*strDottedAddr
,
432 sal_uInt32 nAddr
= OSL_INADDR_NONE
;
435 if (strDottedAddr
&& strDottedAddr
->length
)
437 /* Dotted host address for limited broadcast */
438 rtl_String
*pDottedAddr
= nullptr;
441 &pDottedAddr
, strDottedAddr
->buffer
, strDottedAddr
->length
,
442 RTL_TEXTENCODING_UTF8
, OUSTRING_TO_OSTRING_CVTFLAGS
);
444 nAddr
= inet_addr (pDottedAddr
->buffer
);
445 rtl_string_release (pDottedAddr
);
448 if (nAddr
!= OSL_INADDR_NONE
)
450 /* Limited broadcast */
451 nAddr
= ntohl(nAddr
);
452 if (IN_CLASSA(nAddr
))
454 nAddr
&= IN_CLASSA_NET
;
455 nAddr
|= IN_CLASSA_HOST
;
457 else if (IN_CLASSB(nAddr
))
459 nAddr
&= IN_CLASSB_NET
;
460 nAddr
|= IN_CLASSB_HOST
;
462 else if (IN_CLASSC(nAddr
))
464 nAddr
&= IN_CLASSC_NET
;
465 nAddr
|= IN_CLASSC_HOST
;
469 /* No broadcast in class D */
472 nAddr
= htonl(nAddr
);
475 pAddr
= createSocketAddrWithFamily( osl_Socket_FamilyInet
, htons(Port
), nAddr
);
479 oslSocketAddr SAL_CALL
osl_createInetSocketAddr (
480 rtl_uString
*ustrDottedAddr
,
483 rtl_String
* strDottedAddr
=nullptr;
485 sal_Char
* pszDottedAddr
=nullptr;
487 if ( ustrDottedAddr
!= nullptr )
489 rtl_uString2String( &strDottedAddr
,
490 rtl_uString_getStr(ustrDottedAddr
),
491 rtl_uString_getLength(ustrDottedAddr
),
492 RTL_TEXTENCODING_UTF8
,
493 OUSTRING_TO_OSTRING_CVTFLAGS
);
494 pszDottedAddr
= rtl_string_getStr(strDottedAddr
);
497 Addr
= pszDottedAddr
? osl_psz_createInetSocketAddr(pszDottedAddr
, Port
) : nullptr;
499 if ( strDottedAddr
!= nullptr )
501 rtl_string_release(strDottedAddr
);
507 oslSocketAddr
osl_psz_createInetSocketAddr (
508 const sal_Char
* pszDottedAddr
,
511 oslSocketAddr pAddr
= nullptr;
512 sal_Int32 Addr
= inet_addr(pszDottedAddr
);
515 /* valid dotted addr */
516 pAddr
= createSocketAddrWithFamily( osl_Socket_FamilyInet
, htons(Port
) , Addr
);
521 oslSocketResult SAL_CALL
osl_setAddrOfSocketAddr( oslSocketAddr pAddr
, sal_Sequence
*pByteSeq
)
523 oslSocketResult res
= osl_Socket_Error
;
525 SAL_WARN_IF( !pAddr
, "sal.osl", "setting address of undefined socket address" );
526 SAL_WARN_IF( !pByteSeq
, "sal.osl", "setting undefined address for socket address" );
528 if( pAddr
&& pByteSeq
)
530 struct sockaddr_in
* pSystemInetAddr
;
532 assert( pAddr
->m_sockaddr
.sa_family
== FAMILY_TO_NATIVE( osl_Socket_FamilyInet
) );
533 assert( pByteSeq
->nElements
== 4 );
535 pSystemInetAddr
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
536 memcpy( &(pSystemInetAddr
->sin_addr
) , pByteSeq
->elements
, 4 );
542 oslSocketResult SAL_CALL
osl_getAddrOfSocketAddr( oslSocketAddr pAddr
, sal_Sequence
**ppByteSeq
)
544 oslSocketResult res
= osl_Socket_Error
;
546 SAL_WARN_IF( !pAddr
, "sal.osl", "getting address of undefined socket address" );
547 SAL_WARN_IF( !ppByteSeq
, "sal.osl", "getting address to undefined address pointer" );
549 if( pAddr
&& ppByteSeq
)
551 struct sockaddr_in
* pSystemInetAddr
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
552 rtl_byte_sequence_constructFromArray( ppByteSeq
, reinterpret_cast<sal_Int8
*>(&pSystemInetAddr
->sin_addr
), 4);
558 /** try to figure out a full-qualified hostname, by adding the current domain
559 as given by the domainname program to the given hostname.
560 This function MUST NOT call gethostbyname since pHostName already points
561 to data returned by gethostname and would be garbled: use gethostname_r
565 /* wrap around different interfaces to reentrant gethostbyname */
566 static struct hostent
* osl_gethostbyname_r (
567 const char *name
, struct hostent
*result
,
568 char *buffer
, int buflen
, int *h_errnop
)
570 #if defined(LINUX) || defined(ANDROID) || defined(FREEBSD) || defined(DRAGONFLY)
571 struct hostent
*result_
; /* will be the same as result */
573 e
= gethostbyname_r (name
, result
, buffer
, buflen
,
575 return e
? nullptr : result_
;
577 *h_errnop
= gethostbyname_r (name
, result
, (struct hostent_data
*)buffer
);
579 return *h_errnop
? NULL
: result
;
581 return gethostbyname_r( name
, result
, buffer
, buflen
, h_errnop
);
585 static bool isFullQualifiedDomainName (const sal_Char
*pHostName
)
587 /* a FQDN (aka 'hostname.domain.top_level_domain' )
588 * is a name which contains a dot '.' in it ( would
589 * match as well for 'hostname.' but is good enough
591 return strchr( pHostName
, int('.') ) != nullptr;
594 static sal_Char
* getFullQualifiedDomainName (const sal_Char
*pHostName
)
596 sal_Char
*pFullQualifiedName
= nullptr;
598 if (isFullQualifiedDomainName(pHostName
))
600 pFullQualifiedName
= strdup(pHostName
);
604 struct hostent aHostByName
;
605 struct hostent
*pHostByName
;
606 sal_Char pQualifiedHostBuffer
[ MAX_HOSTBUFFER_SIZE
];
609 pHostByName
= osl_gethostbyname_r (
611 &aHostByName
, pQualifiedHostBuffer
,
612 sizeof(pQualifiedHostBuffer
), &nErrorNo
);
613 if (pHostByName
!= nullptr)
615 pFullQualifiedName
= strdup(pHostByName
->h_name
);
619 return pFullQualifiedName
;
622 struct oslHostAddrImpl
625 oslSocketAddr pSockAddr
;
628 static oslHostAddr
hostentToHostAddr (const struct hostent
*he
)
630 oslHostAddr pAddr
= nullptr;
631 oslSocketAddr pSockAddr
= nullptr;
635 if ((he
== nullptr) || (he
->h_name
== nullptr) || (he
->h_addr_list
[0] == nullptr))
638 cn
= getFullQualifiedDomainName (he
->h_name
);
639 SAL_WARN_IF( !cn
, "sal.osl", "couldn't get full qualified domain name" );
643 pSockAddr
= createSocketAddr();
644 SAL_WARN_IF( !pSockAddr
, "sal.osl", "insufficient memory" );
645 if (pSockAddr
== nullptr)
651 pSockAddr
->m_sockaddr
.sa_family
= he
->h_addrtype
;
652 if (pSockAddr
->m_sockaddr
.sa_family
== FAMILY_TO_NATIVE(osl_Socket_FamilyInet
))
654 struct sockaddr_in
*sin
= reinterpret_cast<sockaddr_in
*>(&pSockAddr
->m_sockaddr
);
656 &(sin
->sin_addr
.s_addr
),
662 /* unknown address family */
663 /* future extensions for new families might be implemented here */
665 SAL_WARN( "sal.osl", "unknown address family" );
667 destroySocketAddr( pSockAddr
);
672 pAddr
= static_cast<oslHostAddr
>(malloc(sizeof(struct oslHostAddrImpl
)));
673 SAL_WARN_IF( !pAddr
, "sal.osl", "allocation error" );
674 if (pAddr
== nullptr)
676 destroySocketAddr( pSockAddr
);
681 pAddr
->pHostName
= cn
;
682 pAddr
->pSockAddr
= pSockAddr
;
687 oslHostAddr SAL_CALL
osl_createHostAddr (
688 rtl_uString
*ustrHostname
,
689 const oslSocketAddr Addr
)
691 oslHostAddr HostAddr
;
692 rtl_String
* strHostname
=nullptr;
693 sal_Char
* pszHostName
=nullptr;
695 if ( ustrHostname
!= nullptr )
697 rtl_uString2String( &strHostname
,
698 rtl_uString_getStr(ustrHostname
),
699 rtl_uString_getLength(ustrHostname
),
700 RTL_TEXTENCODING_UTF8
,
701 OUSTRING_TO_OSTRING_CVTFLAGS
);
702 pszHostName
= rtl_string_getStr(strHostname
);
705 HostAddr
= osl_psz_createHostAddr(pszHostName
,Addr
);
707 if ( strHostname
!= nullptr )
709 rtl_string_release(strHostname
);
715 oslHostAddr
osl_psz_createHostAddr (
716 const sal_Char
*pszHostname
,
717 const oslSocketAddr pAddr
)
719 oslHostAddr pHostAddr
;
722 SAL_WARN_IF( !pszHostname
, "sal.osl", "undefined hostname" );
723 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
724 if ((pszHostname
== nullptr) || (pAddr
== nullptr))
727 cn
= strdup(pszHostname
);
728 SAL_WARN_IF( !cn
, "sal.osl", "insufficient memory" );
732 pHostAddr
= static_cast<oslHostAddr
>(malloc(sizeof(struct oslHostAddrImpl
)));
733 SAL_WARN_IF( !pHostAddr
, "sal.osl", "allocation error" );
734 if (pHostAddr
== nullptr)
740 pHostAddr
->pHostName
= cn
;
741 pHostAddr
->pSockAddr
= osl_copySocketAddr( pAddr
);
746 oslHostAddr SAL_CALL
osl_createHostAddrByName(rtl_uString
*ustrHostname
)
748 oslHostAddr HostAddr
;
749 rtl_String
* strHostname
=nullptr;
750 sal_Char
* pszHostName
=nullptr;
752 if ( ustrHostname
!= nullptr )
754 rtl_uString2String( &strHostname
,
755 rtl_uString_getStr(ustrHostname
),
756 rtl_uString_getLength(ustrHostname
),
757 RTL_TEXTENCODING_UTF8
,
758 OUSTRING_TO_OSTRING_CVTFLAGS
);
759 pszHostName
=rtl_string_getStr(strHostname
);
762 HostAddr
= osl_psz_createHostAddrByName(pszHostName
);
764 if ( strHostname
!= nullptr )
766 rtl_string_release(strHostname
);
772 oslHostAddr
osl_psz_createHostAddrByName (const sal_Char
*pszHostname
)
776 sal_Char heBuffer
[ MAX_HOSTBUFFER_SIZE
];
779 pHe
= osl_gethostbyname_r (
782 sizeof(heBuffer
), &nErrorNo
);
784 return hostentToHostAddr (pHe
);
787 oslHostAddr SAL_CALL
osl_createHostAddrByAddr (const oslSocketAddr pAddr
)
789 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
791 if (pAddr
== nullptr)
794 if (pAddr
->m_sockaddr
.sa_family
== FAMILY_TO_NATIVE(osl_Socket_FamilyInet
))
796 const struct sockaddr_in
*sin
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
797 if (sin
->sin_addr
.s_addr
== htonl(INADDR_ANY
))
800 char host
[MAX_HOSTBUFFER_SIZE
];
801 int res
= getnameinfo(&pAddr
->m_sockaddr
, sizeof(struct sockaddr_in
),
802 host
, sizeof(host
), nullptr, 0, NI_NAMEREQD
);
806 sal_Char
*cn
= getFullQualifiedDomainName(host
);
807 SAL_WARN_IF( !cn
, "sal.osl", "couldn't get full qualified domain name" );
811 oslSocketAddr pSockAddr
= createSocketAddr();
812 SAL_WARN_IF( !pSockAddr
, "sal.osl", "insufficient memory" );
813 if (pSockAddr
== nullptr)
819 memcpy(&pSockAddr
->m_sockaddr
, &pAddr
->m_sockaddr
, sizeof(pAddr
->m_sockaddr
));
821 oslHostAddr pHostAddr
= static_cast<oslHostAddr
>(malloc(sizeof(struct oslHostAddrImpl
)));
822 SAL_WARN_IF( !pAddr
, "sal.osl", "allocation error" );
823 if (pHostAddr
== nullptr)
825 destroySocketAddr(pSockAddr
);
830 pHostAddr
->pHostName
= cn
;
831 pHostAddr
->pSockAddr
= pSockAddr
;
839 oslHostAddr SAL_CALL
osl_copyHostAddr (const oslHostAddr pAddr
)
841 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
844 return osl_psz_createHostAddr (pAddr
->pHostName
, pAddr
->pSockAddr
);
848 void SAL_CALL
osl_getHostnameOfHostAddr (
849 const oslHostAddr Addr
,
850 rtl_uString
**ustrHostname
)
852 const sal_Char
* pHostname
=nullptr;
854 pHostname
= osl_psz_getHostnameOfHostAddr(Addr
);
856 rtl_uString_newFromAscii (ustrHostname
, pHostname
);
859 const sal_Char
* osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr
)
862 return pAddr
->pHostName
;
866 oslSocketAddr SAL_CALL
osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr
)
868 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
871 return pAddr
->pSockAddr
;
875 void SAL_CALL
osl_destroyHostAddr (oslHostAddr pAddr
)
879 if (pAddr
->pHostName
)
880 free (pAddr
->pHostName
);
881 if (pAddr
->pSockAddr
)
882 osl_destroySocketAddr (pAddr
->pSockAddr
);
887 oslSocketResult SAL_CALL
osl_getLocalHostname(rtl_uString
**ustrLocalHostname
)
889 oslSocketResult Result
;
890 sal_Char pszHostname
[1024];
892 pszHostname
[0] = '\0';
894 Result
= osl_psz_getLocalHostname(pszHostname
,sizeof(pszHostname
));
896 rtl_uString_newFromAscii(ustrLocalHostname
,pszHostname
);
901 oslSocketResult
osl_psz_getLocalHostname (
902 sal_Char
*pBuffer
, sal_uInt32 nBufLen
)
904 static sal_Char LocalHostname
[256] = "";
906 if (strlen(LocalHostname
) == 0)
913 return osl_Socket_Error
;
915 if ((strlen(uts
.nodename
) + 1) > nBufLen
)
916 return osl_Socket_Error
;
918 strncpy(LocalHostname
, uts
.nodename
, sizeof( LocalHostname
));
919 #else /* BSD compatible */
920 if (gethostname(LocalHostname
, sizeof(LocalHostname
)-1) != 0)
921 return osl_Socket_Error
;
923 LocalHostname
[sizeof(LocalHostname
)-1] = 0;
925 /* check if we have an FQDN */
926 if (strchr(LocalHostname
, '.') == nullptr)
930 /* no, determine it via dns */
931 Addr
= osl_psz_createHostAddrByName(LocalHostname
);
933 const sal_Char
*pStr
;
934 if ((pStr
= osl_psz_getHostnameOfHostAddr(Addr
)) != nullptr)
936 strncpy(LocalHostname
, pStr
, sizeof( LocalHostname
));
937 LocalHostname
[sizeof(LocalHostname
)-1] = 0;
939 osl_destroyHostAddr(Addr
);
943 if (strlen(LocalHostname
) > 0)
945 strncpy(pBuffer
, LocalHostname
, nBufLen
);
946 pBuffer
[nBufLen
- 1] = '\0';
948 return osl_Socket_Ok
;
951 return osl_Socket_Error
;
954 oslSocketAddr SAL_CALL
osl_resolveHostname(rtl_uString
*ustrHostname
)
957 rtl_String
* strHostname
=nullptr;
958 sal_Char
* pszHostName
=nullptr;
960 if ( ustrHostname
!= nullptr )
962 rtl_uString2String( &strHostname
,
963 rtl_uString_getStr(ustrHostname
),
964 rtl_uString_getLength(ustrHostname
),
965 RTL_TEXTENCODING_UTF8
,
966 OUSTRING_TO_OSTRING_CVTFLAGS
);
967 pszHostName
= rtl_string_getStr(strHostname
);
970 Addr
= osl_psz_resolveHostname(pszHostName
);
972 if ( strHostname
!= nullptr )
974 rtl_string_release(strHostname
);
980 oslSocketAddr
osl_psz_resolveHostname(const sal_Char
* pszHostname
)
982 struct oslHostAddrImpl
*pAddr
= osl_psz_createHostAddrByName(pszHostname
);
986 oslSocketAddr SockAddr
= osl_copySocketAddr(pAddr
->pSockAddr
);
988 osl_destroyHostAddr(pAddr
);
996 sal_Int32 SAL_CALL
osl_getServicePort(rtl_uString
*ustrServicename
, rtl_uString
*ustrProtocol
)
999 rtl_String
* strServicename
=nullptr;
1000 rtl_String
* strProtocol
=nullptr;
1001 sal_Char
* pszServiceName
=nullptr;
1002 sal_Char
* pszProtocol
=nullptr;
1004 if ( ustrServicename
!= nullptr )
1006 rtl_uString2String( &strServicename
,
1007 rtl_uString_getStr(ustrServicename
),
1008 rtl_uString_getLength(ustrServicename
),
1009 RTL_TEXTENCODING_UTF8
,
1010 OUSTRING_TO_OSTRING_CVTFLAGS
);
1011 pszServiceName
= rtl_string_getStr(strServicename
);
1014 if ( ustrProtocol
!= nullptr )
1016 rtl_uString2String( &strProtocol
,
1017 rtl_uString_getStr(ustrProtocol
),
1018 rtl_uString_getLength(ustrProtocol
),
1019 RTL_TEXTENCODING_UTF8
,
1020 OUSTRING_TO_OSTRING_CVTFLAGS
);
1021 pszProtocol
= rtl_string_getStr(strProtocol
);
1024 nPort
= osl_psz_getServicePort(pszServiceName
,pszProtocol
);
1026 if ( strServicename
!= nullptr )
1028 rtl_string_release(strServicename
);
1031 if ( strProtocol
!= nullptr )
1033 rtl_string_release(strProtocol
);
1039 sal_Int32
osl_psz_getServicePort(const sal_Char
* pszServicename
,
1040 const sal_Char
* pszProtocol
)
1044 ps
= getservbyname(pszServicename
, pszProtocol
);
1047 return ntohs(ps
->s_port
);
1049 return OSL_INVALID_PORT
;
1052 void SAL_CALL
osl_destroySocketAddr(oslSocketAddr pAddr
)
1054 destroySocketAddr( pAddr
);
1057 oslAddrFamily SAL_CALL
osl_getFamilyOfSocketAddr(oslSocketAddr pAddr
)
1059 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
1062 return FAMILY_FROM_NATIVE(pAddr
->m_sockaddr
.sa_family
);
1063 return osl_Socket_FamilyInvalid
;
1066 sal_Int32 SAL_CALL
osl_getInetPortOfSocketAddr(oslSocketAddr pAddr
)
1068 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
1072 struct sockaddr_in
* pSystemInetAddr
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
1074 if ( pSystemInetAddr
->sin_family
== FAMILY_TO_NATIVE(osl_Socket_FamilyInet
))
1075 return ntohs(pSystemInetAddr
->sin_port
);
1077 return OSL_INVALID_PORT
;
1080 sal_Bool SAL_CALL
osl_setInetPortOfSocketAddr(oslSocketAddr pAddr
, sal_Int32 Port
)
1082 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
1086 struct sockaddr_in
* pSystemInetAddr
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
1087 if ( pSystemInetAddr
->sin_family
== FAMILY_TO_NATIVE(osl_Socket_FamilyInet
))
1089 pSystemInetAddr
->sin_port
= htons(static_cast<short>(Port
));
1094 /* this is not a inet-addr => can't set port */
1098 oslSocketResult SAL_CALL
osl_getHostnameOfSocketAddr(oslSocketAddr Addr
, rtl_uString
**ustrHostname
)
1100 oslSocketResult Result
;
1101 sal_Char pszHostname
[1024];
1103 pszHostname
[0] = '\0';
1105 Result
= osl_psz_getHostnameOfSocketAddr(Addr
,pszHostname
,sizeof(pszHostname
));
1106 if (Result
== osl_Socket_Ok
)
1108 rtl_uString_newFromAscii(ustrHostname
,pszHostname
);
1114 oslSocketResult
osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr
,
1115 sal_Char
*pBuffer
, sal_uInt32 BufferSize
)
1117 oslHostAddr pHostAddr
= osl_createHostAddrByAddr(pAddr
);
1121 strncpy(pBuffer
, pHostAddr
->pHostName
, BufferSize
);
1122 pBuffer
[BufferSize
- 1] = '\0';
1124 osl_destroyHostAddr(pHostAddr
);
1126 return osl_Socket_Ok
;
1129 return osl_Socket_Error
;
1132 oslSocketResult SAL_CALL
osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr
, rtl_uString
**ustrDottedInetAddr
)
1134 oslSocketResult Result
;
1135 sal_Char pszDottedInetAddr
[1024];
1137 pszDottedInetAddr
[0] = '\0';
1139 Result
= osl_psz_getDottedInetAddrOfSocketAddr(Addr
,pszDottedInetAddr
,sizeof(pszDottedInetAddr
));
1141 rtl_uString_newFromAscii(ustrDottedInetAddr
,pszDottedInetAddr
);
1147 oslSocketResult
osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr
,
1148 sal_Char
*pBuffer
, sal_uInt32 BufferSize
)
1150 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
1154 struct sockaddr_in
* pSystemInetAddr
= reinterpret_cast<sockaddr_in
*>(&pAddr
->m_sockaddr
);
1156 if (pSystemInetAddr
->sin_family
== FAMILY_TO_NATIVE(osl_Socket_FamilyInet
))
1158 strncpy(pBuffer
, inet_ntoa(pSystemInetAddr
->sin_addr
), BufferSize
);
1159 pBuffer
[BufferSize
- 1] = '\0';
1161 return osl_Socket_Ok
;
1165 return osl_Socket_Error
;
1168 oslSocket SAL_CALL
osl_createSocket(
1169 oslAddrFamily Family
,
1171 oslProtocol Protocol
)
1176 pSocket
= createSocketImpl(OSL_INVALID_SOCKET
);
1179 pSocket
->m_Socket
= socket(FAMILY_TO_NATIVE(Family
),
1180 TYPE_TO_NATIVE(Type
),
1181 PROTOCOL_TO_NATIVE(Protocol
));
1183 /* creation failed => free memory */
1184 if(pSocket
->m_Socket
== OSL_INVALID_SOCKET
)
1187 SAL_WARN( "sal.osl", "socket creation failed: " << UnixErrnoString(nErrno
) );
1189 destroySocketImpl(pSocket
);
1195 /* set close-on-exec flag */
1196 if ((nFlags
= fcntl(pSocket
->m_Socket
, F_GETFD
, 0)) != -1)
1198 nFlags
|= FD_CLOEXEC
;
1199 if (fcntl(pSocket
->m_Socket
, F_SETFD
, nFlags
) == -1)
1201 pSocket
->m_nLastError
=errno
;
1203 SAL_WARN( "sal.osl", "failed changing socket flags: " << UnixErrnoString(nErrno
) );
1208 pSocket
->m_nLastError
=errno
;
1215 void SAL_CALL
osl_acquireSocket(oslSocket pSocket
)
1217 osl_atomic_increment(&(pSocket
->m_nRefCount
));
1220 void SAL_CALL
osl_releaseSocket(oslSocket pSocket
)
1222 if (pSocket
&& osl_atomic_decrement(&(pSocket
->m_nRefCount
)) == 0)
1224 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1225 if (pSocket
->m_bIsAccepting
)
1227 SAL_WARN( "sal.osl", "attempt to destroy socket while accepting" );
1230 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1231 osl_closeSocket(pSocket
);
1232 destroySocketImpl(pSocket
);
1236 void SAL_CALL
osl_closeSocket(oslSocket pSocket
)
1238 /* socket already invalid */
1242 pSocket
->m_nLastError
=0;
1243 sal_Int32 nFD
= pSocket
->m_Socket
;
1245 if (nFD
== OSL_INVALID_SOCKET
)
1248 pSocket
->m_Socket
= OSL_INVALID_SOCKET
;
1251 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1252 pSocket
->m_bIsInShutdown
= true;
1254 if (pSocket
->m_bIsAccepting
)
1257 struct sockaddr aSockAddr
;
1258 struct sockaddr_in aSockAddrIn
;
1260 socklen_t nSockLen
= sizeof(s
.aSockAddr
);
1262 nRet
= getsockname(nFD
, &s
.aSockAddr
, &nSockLen
);
1266 SAL_WARN( "sal.osl", "getsockname call failed: " << UnixErrnoString(nErrno
) );
1269 if (s
.aSockAddr
.sa_family
== AF_INET
)
1271 if (s
.aSockAddrIn
.sin_addr
.s_addr
== htonl(INADDR_ANY
))
1273 s
.aSockAddrIn
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1276 int nConnFD
= socket(AF_INET
, SOCK_STREAM
, 0);
1280 SAL_WARN( "sal.osl", "socket call failed: " << UnixErrnoString(nErrno
) );
1284 nRet
= connect(nConnFD
, &s
.aSockAddr
, sizeof(s
.aSockAddr
));
1288 SAL_WARN( "sal.osl", "connect call failed: " << UnixErrnoString(nErrno
) );
1293 pSocket
->m_bIsAccepting
= false;
1295 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1300 pSocket
->m_nLastError
=errno
;
1302 SAL_WARN( "sal.osl", "closeSocket close failed: " << UnixErrnoString(nErrno
) );
1305 pSocket
->m_Socket
= OSL_INVALID_SOCKET
;
1308 /* Note from function creator: I rely on the fact that oslSocketAddr and struct sockaddr
1309 are the same! I don't like it very much but see no other easy way to conceal
1310 the struct sockaddr from the eyes of the user. */
1311 oslSocketAddr SAL_CALL
osl_getLocalAddrOfSocket(oslSocket pSocket
)
1314 struct sockaddr Addr
;
1315 oslSocketAddr pAddr
;
1317 if (pSocket
== nullptr) /* ENOTSOCK */
1320 AddrLen
= sizeof(struct sockaddr
);
1322 if (getsockname(pSocket
->m_Socket
, &Addr
, &AddrLen
) == OSL_SOCKET_ERROR
)
1325 pAddr
= createSocketAddrFromSystem( &Addr
);
1329 oslSocketAddr SAL_CALL
osl_getPeerAddrOfSocket(oslSocket pSocket
)
1332 struct sockaddr Addr
;
1334 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1335 if ( pSocket
== nullptr )
1340 pSocket
->m_nLastError
=0;
1341 AddrLen
= sizeof(struct sockaddr
);
1343 if(getpeername(pSocket
->m_Socket
, &Addr
, &AddrLen
) == OSL_SOCKET_ERROR
)
1345 pSocket
->m_nLastError
=errno
;
1348 return createSocketAddrFromSystem( &Addr
);
1351 sal_Bool SAL_CALL
osl_bindAddrToSocket(oslSocket pSocket
,
1352 oslSocketAddr pAddr
)
1356 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1357 SAL_WARN_IF( !pAddr
, "sal.osl", "undefined address" );
1358 if ( pSocket
== nullptr || pAddr
== nullptr )
1363 pSocket
->m_nLastError
=0;
1365 nRet
= bind(pSocket
->m_Socket
, &(pAddr
->m_sockaddr
), sizeof(struct sockaddr
));
1367 if ( nRet
== OSL_SOCKET_ERROR
)
1369 pSocket
->m_nLastError
=errno
;
1376 sal_Bool SAL_CALL
osl_listenOnSocket(oslSocket pSocket
,
1377 sal_Int32 MaxPendingConnections
)
1381 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1382 if ( pSocket
== nullptr )
1387 pSocket
->m_nLastError
=0;
1389 nRet
= listen(pSocket
->m_Socket
,
1390 MaxPendingConnections
== -1 ?
1392 MaxPendingConnections
);
1393 if ( nRet
== OSL_SOCKET_ERROR
)
1395 pSocket
->m_nLastError
=errno
;
1402 oslSocketResult SAL_CALL
osl_connectSocketTo(oslSocket pSocket
,
1403 oslSocketAddr pAddr
,
1404 const TimeValue
* pTimeout
)
1411 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1413 if ( pSocket
== nullptr )
1415 return osl_Socket_Error
;
1418 pSocket
->m_nLastError
=0;
1420 if (osl_isNonBlockingMode(pSocket
))
1422 if (connect(pSocket
->m_Socket
,
1423 &(pAddr
->m_sockaddr
),
1424 sizeof(struct sockaddr
)) != OSL_SOCKET_ERROR
)
1425 return osl_Socket_Ok
;
1427 if (errno
== EWOULDBLOCK
|| errno
== EINPROGRESS
)
1429 pSocket
->m_nLastError
=EINPROGRESS
;
1430 return osl_Socket_InProgress
;
1433 pSocket
->m_nLastError
=errno
;
1435 SAL_WARN( "sal.osl", "connection failed: " << UnixErrnoString(nErrno
) );
1436 return osl_Socket_Error
;
1439 /* set socket temporarily to non-blocking */
1440 if( !osl_enableNonBlockingMode(pSocket
, true) )
1441 SAL_WARN( "sal.osl", "failed to enable non-blocking mode" );
1443 /* initiate connect */
1444 if(connect(pSocket
->m_Socket
,
1445 &(pAddr
->m_sockaddr
),
1446 sizeof(struct sockaddr
)) != OSL_SOCKET_ERROR
)
1448 /* immediate connection */
1449 osl_enableNonBlockingMode(pSocket
, false);
1451 return osl_Socket_Ok
;
1454 /* really an error or just delayed? */
1455 if (errno
!= EINPROGRESS
)
1457 pSocket
->m_nLastError
=errno
;
1459 SAL_WARN( "sal.osl", "connection failed: " << UnixErrnoString(nErrno
) );
1461 osl_enableNonBlockingMode(pSocket
, false);
1462 return osl_Socket_Error
;
1465 /* prepare select set for socket */
1468 FD_SET(pSocket
->m_Socket
, &WriteSet
);
1469 FD_SET(pSocket
->m_Socket
, &ExcptSet
);
1471 /* prepare timeout */
1474 /* divide milliseconds into seconds and microseconds */
1475 tv
.tv_sec
= pTimeout
->Seconds
;
1476 tv
.tv_usec
= pTimeout
->Nanosec
/ 1000L;
1480 ReadyHandles
= select(pSocket
->m_Socket
+1,
1482 PTR_FD_SET(WriteSet
),
1483 PTR_FD_SET(ExcptSet
),
1484 pTimeout
? &tv
: nullptr);
1486 if (ReadyHandles
> 0) /* connected */
1488 if ( FD_ISSET(pSocket
->m_Socket
, &WriteSet
) )
1491 socklen_t nErrorSize
= sizeof( nErrorCode
);
1495 nSockOpt
= getsockopt ( pSocket
->m_Socket
, SOL_SOCKET
, SO_ERROR
,
1496 &nErrorCode
, &nErrorSize
);
1497 if ( (nSockOpt
== 0) && (nErrorCode
== 0))
1499 osl_enableNonBlockingMode(pSocket
, false);
1500 return osl_Socket_Ok
;
1504 pSocket
->m_nLastError
= (nSockOpt
== 0) ? nErrorCode
: errno
;
1505 return osl_Socket_Error
;
1510 return osl_Socket_Error
;
1513 else if (ReadyHandles
< 0) /* error */
1515 if (errno
== EBADF
) /* most probably interrupted by close() */
1517 /* do not access pSockImpl because it is about to be or */
1518 /* already destroyed */
1519 return osl_Socket_Interrupted
;
1521 pSocket
->m_nLastError
=errno
;
1522 return osl_Socket_Error
;
1526 pSocket
->m_nLastError
=errno
;
1527 return osl_Socket_TimedOut
;
1531 oslSocket SAL_CALL
osl_acceptConnectionOnSocket(oslSocket pSocket
,
1532 oslSocketAddr
* ppAddr
)
1534 struct sockaddr Addr
;
1535 int Connection
, Flags
;
1536 oslSocket pConnectionSockImpl
;
1538 socklen_t AddrLen
= sizeof(struct sockaddr
);
1539 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1540 if ( pSocket
== nullptr )
1545 pSocket
->m_nLastError
=0;
1546 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1547 pSocket
->m_bIsAccepting
= true;
1548 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1550 if( ppAddr
&& *ppAddr
)
1552 osl_destroySocketAddr( *ppAddr
);
1556 /* prevent Linux EINTR behaviour */
1559 Connection
= accept(pSocket
->m_Socket
, &Addr
, &AddrLen
);
1560 } while (Connection
== -1 && errno
== EINTR
);
1562 /* accept failed? */
1563 if( Connection
== OSL_SOCKET_ERROR
)
1565 pSocket
->m_nLastError
=errno
;
1567 SAL_WARN( "sal.osl", "accept connection failed: " << UnixErrnoString(nErrno
) );
1569 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1570 pSocket
->m_bIsAccepting
= false;
1571 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1575 assert(AddrLen
== sizeof(struct sockaddr
));
1577 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1578 if ( pSocket
->m_bIsInShutdown
)
1581 SAL_WARN( "sal.osl", "close while accept" );
1584 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1588 *ppAddr
= createSocketAddrFromSystem(&Addr
);
1592 pConnectionSockImpl
= createSocketImpl(OSL_INVALID_SOCKET
);
1594 /* set close-on-exec flag */
1595 if ((Flags
= fcntl(Connection
, F_GETFD
, 0)) != -1)
1597 Flags
|= FD_CLOEXEC
;
1598 if (fcntl(Connection
, F_SETFD
, Flags
) == -1)
1600 pSocket
->m_nLastError
=errno
;
1602 SAL_WARN( "sal.osl", "fcntl failed: " << UnixErrnoString(nErrno
) );
1607 pConnectionSockImpl
->m_Socket
= Connection
;
1608 pConnectionSockImpl
->m_nLastError
= 0;
1609 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1610 pConnectionSockImpl
->m_bIsAccepting
= false;
1612 pSocket
->m_bIsAccepting
= false;
1613 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1614 return pConnectionSockImpl
;
1617 sal_Int32 SAL_CALL
osl_receiveSocket(oslSocket pSocket
,
1619 sal_uInt32 BytesToRead
,
1620 oslSocketMsgFlag Flag
)
1624 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1625 if ( pSocket
== nullptr )
1630 pSocket
->m_nLastError
=0;
1634 nRead
= recv(pSocket
->m_Socket
,
1637 MSG_FLAG_TO_NATIVE(Flag
));
1638 } while ( nRead
< 0 && errno
== EINTR
);
1642 pSocket
->m_nLastError
=errno
;
1644 SAL_WARN( "sal.osl", "receive socket [" << nRead
<< "] failed: " << UnixErrnoString(nErrno
) );
1646 else if ( nRead
== 0 )
1648 SAL_WARN( "sal.osl", "receive socket [" << nRead
<< "] failed: EOL" );
1654 sal_Int32 SAL_CALL
osl_receiveFromSocket(oslSocket pSocket
,
1655 oslSocketAddr pSenderAddr
,
1657 sal_uInt32 BufferSize
,
1658 oslSocketMsgFlag Flag
)
1661 struct sockaddr
*pSystemSockAddr
= nullptr;
1662 socklen_t AddrLen
= 0;
1665 AddrLen
= sizeof( struct sockaddr
);
1666 pSystemSockAddr
= &(pSenderAddr
->m_sockaddr
);
1669 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1670 if ( pSocket
== nullptr )
1675 pSocket
->m_nLastError
=0;
1677 nRead
= recvfrom(pSocket
->m_Socket
,
1680 MSG_FLAG_TO_NATIVE(Flag
),
1686 pSocket
->m_nLastError
=errno
;
1688 SAL_WARN( "sal.osl", "receive socket [" << nRead
<< "] failed: " << UnixErrnoString(nErrno
) );
1690 else if ( nRead
== 0 )
1692 SAL_WARN( "sal.osl", "receive socket [" << nRead
<< "] failed: EOL" );
1698 sal_Int32 SAL_CALL
osl_sendSocket(oslSocket pSocket
,
1699 const void* pBuffer
,
1700 sal_uInt32 BytesToSend
,
1701 oslSocketMsgFlag Flag
)
1705 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1706 if ( pSocket
== nullptr )
1711 pSocket
->m_nLastError
=0;
1715 nWritten
= send(pSocket
->m_Socket
,
1718 MSG_FLAG_TO_NATIVE(Flag
));
1719 } while ( nWritten
< 0 && errno
== EINTR
);
1723 pSocket
->m_nLastError
=errno
;
1725 SAL_WARN( "sal.osl", "send socket [" << nWritten
<< "] failed: " << UnixErrnoString(nErrno
) );
1727 else if ( nWritten
== 0 )
1729 SAL_WARN( "sal.osl", "send socket [" << nWritten
<< "] failed: EOL" );
1735 sal_Int32 SAL_CALL
osl_sendToSocket(oslSocket pSocket
,
1736 oslSocketAddr ReceiverAddr
,
1737 const void* pBuffer
,
1738 sal_uInt32 BytesToSend
,
1739 oslSocketMsgFlag Flag
)
1743 struct sockaddr
*pSystemSockAddr
= nullptr;
1747 pSystemSockAddr
= &(ReceiverAddr
->m_sockaddr
);
1748 AddrLen
= sizeof( struct sockaddr
);
1751 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1752 if ( pSocket
== nullptr )
1757 pSocket
->m_nLastError
=0;
1759 /* ReceiverAddr might be 0 when used on a connected socket. */
1760 /* Then sendto should behave like send. */
1762 nWritten
= sendto(pSocket
->m_Socket
,
1765 MSG_FLAG_TO_NATIVE(Flag
),
1771 pSocket
->m_nLastError
=errno
;
1773 SAL_WARN( "sal.osl", "send socket [" << nWritten
<< "] failed: " << UnixErrnoString(nErrno
) );
1775 else if ( nWritten
== 0 )
1777 SAL_WARN( "sal.osl", "send socket [" << nWritten
<< "] failed: EOL" );
1783 sal_Int32 SAL_CALL
osl_readSocket (
1784 oslSocket pSocket
, void *pBuffer
, sal_Int32 n
)
1786 sal_uInt8
* Ptr
= static_cast<sal_uInt8
*>(pBuffer
);
1787 sal_uInt32 BytesRead
= 0;
1788 sal_uInt32 BytesToRead
= n
;
1790 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1792 /* loop until all desired bytes were read or an error occurred */
1793 while (BytesToRead
> 0)
1796 RetVal
= osl_receiveSocket(pSocket
,
1799 osl_Socket_MsgNormal
);
1801 /* error occurred? */
1807 BytesToRead
-= RetVal
;
1808 BytesRead
+= RetVal
;
1815 sal_Int32 SAL_CALL
osl_writeSocket(
1816 oslSocket pSocket
, const void *pBuffer
, sal_Int32 n
)
1818 /* loop until all desired bytes were send or an error occurred */
1819 sal_uInt32 BytesSend
= 0;
1820 sal_uInt32 BytesToSend
= n
;
1821 sal_uInt8
const *Ptr
= static_cast<sal_uInt8
const *>(pBuffer
);
1823 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1825 while (BytesToSend
> 0)
1829 RetVal
= osl_sendSocket( pSocket
,Ptr
,BytesToSend
,osl_Socket_MsgNormal
);
1831 /* error occurred? */
1837 BytesToSend
-= RetVal
;
1838 BytesSend
+= RetVal
;
1845 #ifdef HAVE_POLL_H /* poll() */
1847 static bool socket_poll (
1849 const TimeValue
* pTimeout
,
1856 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1857 if (pSocket
== nullptr)
1858 return false; /* EINVAL */
1860 pSocket
->m_nLastError
= 0;
1862 fds
.fd
= pSocket
->m_Socket
;
1863 fds
.events
= nEvent
;
1869 /* Convert to [ms] */
1870 timeout
= pTimeout
->Seconds
* 1000;
1871 timeout
+= pTimeout
->Nanosec
/ (1000 * 1000);
1874 result
= poll (&fds
, 1, timeout
);
1877 pSocket
->m_nLastError
= errno
;
1879 SAL_WARN( "sal.osl", "poll failed: " << UnixErrnoString(nErrno
) );
1888 return ((fds
.revents
& nEvent
) == nEvent
);
1891 #else /* select() */
1893 static sal_Bool
socket_poll (
1895 const TimeValue
* pTimeout
,
1902 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1904 return sal_False
; /* EINVAL */
1906 pSocket
->m_nLastError
= 0;
1909 FD_SET(pSocket
->m_Socket
, &fds
);
1913 /* Convert to 'timeval' */
1914 tv
.tv_sec
= pTimeout
->Seconds
;
1915 tv
.tv_usec
= pTimeout
->Nanosec
/ 1000;
1919 pSocket
->m_Socket
+ 1,
1920 (nEvent
== POLLIN
) ? PTR_FD_SET(fds
) : NULL
,
1921 (nEvent
== POLLOUT
) ? PTR_FD_SET(fds
) : NULL
,
1922 (nEvent
== POLLPRI
) ? PTR_FD_SET(fds
) : NULL
,
1923 (pTimeout
) ? &tv
: NULL
);
1927 pSocket
->m_nLastError
= errno
;
1929 SAL_WARN( "sal.osl", "select failed: " << UnixErrnoString(nErrno
) );
1938 return (FD_ISSET(pSocket
->m_Socket
, &fds
) ? sal_True
: sal_False
);
1941 #endif /* HAVE_POLL_H */
1943 sal_Bool SAL_CALL
osl_isReceiveReady (
1944 oslSocket pSocket
, const TimeValue
* pTimeout
)
1946 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1947 if (pSocket
== nullptr)
1953 return socket_poll (pSocket
, pTimeout
, POLLIN
);
1956 sal_Bool SAL_CALL
osl_isSendReady (
1957 oslSocket pSocket
, const TimeValue
* pTimeout
)
1959 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1960 if (pSocket
== nullptr)
1966 return socket_poll (pSocket
, pTimeout
, POLLOUT
);
1969 sal_Bool SAL_CALL
osl_isExceptionPending (
1970 oslSocket pSocket
, const TimeValue
* pTimeout
)
1972 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1973 if (pSocket
== nullptr)
1979 return socket_poll (pSocket
, pTimeout
, POLLPRI
);
1982 sal_Bool SAL_CALL
osl_shutdownSocket(oslSocket pSocket
,
1983 oslSocketDirection Direction
)
1987 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
1988 if ( pSocket
== nullptr )
1993 pSocket
->m_nLastError
=0;
1995 nRet
=shutdown(pSocket
->m_Socket
, DIRECTION_TO_NATIVE(Direction
));
1998 pSocket
->m_nLastError
=errno
;
2000 SAL_WARN( "sal.osl", "shutdown failed: " << UnixErrnoString(nErrno
) );
2005 sal_Int32 SAL_CALL
osl_getSocketOption(oslSocket pSocket
,
2006 oslSocketOptionLevel Level
,
2007 oslSocketOption Option
,
2009 sal_uInt32 BufferLen
)
2011 socklen_t nOptLen
= static_cast<socklen_t
>(BufferLen
);
2013 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2014 if ( pSocket
== nullptr )
2019 pSocket
->m_nLastError
=0;
2021 if(getsockopt(pSocket
->m_Socket
,
2022 OPTION_LEVEL_TO_NATIVE(Level
),
2023 OPTION_TO_NATIVE(Option
),
2027 pSocket
->m_nLastError
=errno
;
2034 sal_Bool SAL_CALL
osl_setSocketOption(oslSocket pSocket
,
2035 oslSocketOptionLevel Level
,
2036 oslSocketOption Option
,
2038 sal_uInt32 BufferLen
)
2042 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2043 if ( pSocket
== nullptr )
2048 pSocket
->m_nLastError
=0;
2050 nRet
= setsockopt(pSocket
->m_Socket
,
2051 OPTION_LEVEL_TO_NATIVE(Level
),
2052 OPTION_TO_NATIVE(Option
),
2058 pSocket
->m_nLastError
=errno
;
2065 sal_Bool SAL_CALL
osl_enableNonBlockingMode(oslSocket pSocket
,
2071 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2072 if ( pSocket
== nullptr )
2077 pSocket
->m_nLastError
=0;
2079 flags
= fcntl(pSocket
->m_Socket
, F_GETFL
, 0);
2082 flags
|= O_NONBLOCK
;
2084 flags
&= ~(O_NONBLOCK
);
2086 nRet
= fcntl(pSocket
->m_Socket
, F_SETFL
, flags
);
2090 pSocket
->m_nLastError
=errno
;
2097 sal_Bool SAL_CALL
osl_isNonBlockingMode(oslSocket pSocket
)
2101 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2102 if ( pSocket
== nullptr )
2107 pSocket
->m_nLastError
=0;
2109 flags
= fcntl(pSocket
->m_Socket
, F_GETFL
, 0);
2111 if (flags
== -1 || !(flags
& O_NONBLOCK
))
2117 oslSocketType SAL_CALL
osl_getSocketType(oslSocket pSocket
)
2120 socklen_t TypeSize
= sizeof(Type
);
2122 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2123 if ( pSocket
== nullptr )
2125 return osl_Socket_TypeInvalid
;
2128 pSocket
->m_nLastError
=0;
2130 if(getsockopt(pSocket
->m_Socket
,
2131 OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket
),
2132 OPTION_TO_NATIVE(osl_Socket_OptionType
),
2137 pSocket
->m_nLastError
=errno
;
2138 return osl_Socket_TypeInvalid
;
2141 return TYPE_FROM_NATIVE(Type
);
2145 void SAL_CALL
osl_getLastSocketErrorDescription(oslSocket Socket
, rtl_uString
**ustrError
)
2147 sal_Char pszError
[1024];
2151 osl_psz_getLastSocketErrorDescription(Socket
,pszError
,sizeof(pszError
));
2153 rtl_uString_newFromAscii(ustrError
,pszError
);
2156 void osl_psz_getLastSocketErrorDescription(oslSocket pSocket
, sal_Char
* pBuffer
, sal_uInt32 BufferSize
)
2158 /* make sure pBuffer will be a zero-terminated string even when strncpy has to cut */
2159 pBuffer
[BufferSize
-1]= '\0';
2161 if ( pSocket
== nullptr )
2163 strncpy(pBuffer
, strerror(EINVAL
), BufferSize
-1);
2167 strncpy(pBuffer
, strerror(pSocket
->m_nLastError
), BufferSize
-1);
2170 oslSocketError SAL_CALL
osl_getLastSocketError(oslSocket pSocket
)
2172 if ( pSocket
== nullptr )
2174 return ERROR_FROM_NATIVE(EINVAL
);
2177 return ERROR_FROM_NATIVE(pSocket
->m_nLastError
);
2180 struct oslSocketSetImpl
2182 int m_MaxHandle
; /* for select(), the largest descriptor in the set */
2183 fd_set m_Set
; /* the set of descriptors */
2187 oslSocketSet SAL_CALL
osl_createSocketSet()
2189 oslSocketSetImpl
* pSet
;
2191 pSet
= static_cast<oslSocketSetImpl
*>(malloc(sizeof(oslSocketSetImpl
)));
2193 SAL_WARN_IF( !pSet
, "sal.osl", "allocation error" );
2197 pSet
->m_MaxHandle
= 0;
2198 FD_ZERO(&pSet
->m_Set
);
2204 void SAL_CALL
osl_destroySocketSet(oslSocketSet Set
)
2210 void SAL_CALL
osl_clearSocketSet(oslSocketSet Set
)
2212 SAL_WARN_IF( !Set
, "sal.osl", "undefined socket set" );
2213 if ( Set
== nullptr )
2218 Set
->m_MaxHandle
= 0;
2220 FD_ZERO(&Set
->m_Set
);
2223 void SAL_CALL
osl_addToSocketSet(oslSocketSet Set
, oslSocket pSocket
)
2225 SAL_WARN_IF( !Set
, "sal.osl", "undefined socket set" );
2226 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2228 if ( Set
== nullptr || pSocket
== nullptr)
2233 /* correct max handle */
2234 if(pSocket
->m_Socket
> Set
->m_MaxHandle
)
2235 Set
->m_MaxHandle
= pSocket
->m_Socket
;
2236 FD_SET(pSocket
->m_Socket
, &Set
->m_Set
);
2240 void SAL_CALL
osl_removeFromSocketSet(oslSocketSet Set
, oslSocket pSocket
)
2242 SAL_WARN_IF( !Set
, "sal.osl", "undefined socket set" );
2243 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2245 if ( Set
== nullptr || pSocket
== nullptr)
2250 /* correct max handle */
2251 if(pSocket
->m_Socket
== Set
->m_MaxHandle
)
2253 /* not optimal, since the next used descriptor might be */
2254 /* much smaller than m_Socket-1, but it will do */
2256 if(Set
->m_MaxHandle
< 0)
2258 Set
->m_MaxHandle
= 0; /* avoid underflow */
2262 FD_CLR(pSocket
->m_Socket
, &Set
->m_Set
);
2265 sal_Bool SAL_CALL
osl_isInSocketSet(oslSocketSet Set
, oslSocket pSocket
)
2267 SAL_WARN_IF( !Set
, "sal.osl", "undefined socket set" );
2268 SAL_WARN_IF( !pSocket
, "sal.osl", "undefined socket" );
2269 if ( Set
== nullptr || pSocket
== nullptr )
2274 return bool(FD_ISSET(pSocket
->m_Socket
, &Set
->m_Set
));
2277 sal_Int32 SAL_CALL
osl_demultiplexSocketEvents(oslSocketSet IncomingSet
,
2278 oslSocketSet OutgoingSet
,
2279 oslSocketSet OutOfBandSet
,
2280 const TimeValue
* pTimeout
)
2287 /* non-blocking call */
2288 tv
.tv_sec
= pTimeout
->Seconds
;
2289 tv
.tv_usec
= pTimeout
->Nanosec
/ 1000L;
2292 /* get max handle from all sets */
2294 MaxHandle
= IncomingSet
->m_MaxHandle
;
2296 if (OutgoingSet
&& (OutgoingSet
->m_MaxHandle
> MaxHandle
))
2297 MaxHandle
= OutgoingSet
->m_MaxHandle
;
2299 if (OutOfBandSet
&& (OutOfBandSet
->m_MaxHandle
> MaxHandle
))
2300 MaxHandle
= OutOfBandSet
->m_MaxHandle
;
2302 return select(MaxHandle
+1,
2303 IncomingSet
? PTR_FD_SET(IncomingSet
->m_Set
) : nullptr,
2304 OutgoingSet
? PTR_FD_SET(OutgoingSet
->m_Set
) : nullptr,
2305 OutOfBandSet
? PTR_FD_SET(OutOfBandSet
->m_Set
) : nullptr,
2306 pTimeout
? &tv
: nullptr);
2309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */