Avoid potential negative array index access to cached text.
[LibreOffice.git] / sal / osl / unx / socket.cxx
blobe875e415e709e19e5102e680baf519d00516b7e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <sal/config.h>
22 #include <utility>
24 #include "system.hxx"
26 #include <osl/socket.h>
28 #include <rtl/alloc.h>
29 #include <rtl/byteseq.h>
30 #include <rtl/ustring.hxx>
31 #include <assert.h>
32 #include <sal/types.h>
33 #include <sal/log.hxx>
35 #include "sockimpl.hxx"
36 #include "unixerrnostring.hxx"
37 #include <oslsocket.hxx>
39 #include <arpa/inet.h>
40 #include <fcntl.h>
41 #include <netdb.h>
42 #include <netinet/tcp.h>
43 #include <poll.h>
44 #include <unistd.h>
46 /* defines for shutdown */
47 #define SD_RECEIVE 0
48 #define SD_SEND 1
49 #define SD_BOTH 2
52 oslSocketAddr is a pointer to a Berkeley struct sockaddr.
53 I refrained from using sockaddr_in because of possible further
54 extensions of this socket-interface (IP-NG?).
55 The intention was to hide all Berkeley data-structures from
56 direct access past the osl-interface.
58 The current implementation is internet (IP) centered. All
59 the constructor-functions (osl_create...) take parameters
60 that will probably make sense only in the IP-environment
61 (e.g. because of using the dotted-address-format).
63 If the interface will be extended to host other protocol-
64 families, I expect no externally visible changes in the
65 existing functions. You'll probably need only new
66 constructor-functions who take the different address
67 formats into consideration (maybe a long dotted address
68 or whatever).
71 /* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */
72 /* are the same! I don't like it very much but see no other easy way to */
73 /* conceal the struct sockaddr from the eyes of the user. */
75 #define OSL_INVALID_SOCKET -1
76 #define OSL_SOCKET_ERROR -1
78 /* Buffer size for getnameinfo */
79 #define MAX_HOSTBUFFER_SIZE 2048
81 const unsigned long FamilyMap[]= {
82 AF_INET, /* osl_Socket_FamilyInet */
83 AF_IPX, /* osl_Socket_FamilyIpx */
84 0 /* osl_Socket_FamilyInvalid */
87 static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
89 oslAddrFamily i= oslAddrFamily(0);
91 while(i != osl_Socket_FamilyInvalid)
93 if(FamilyMap[i] == nativeType)
94 return i;
95 i = static_cast<oslAddrFamily>( i + 1 );
98 return i;
101 #define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
102 #define FAMILY_TO_NATIVE(x) static_cast<short>(FamilyMap[x])
104 const sal_uInt32 ProtocolMap[]= {
105 0, /* osl_Socket_ProtocolIp */
106 NSPROTO_IPX, /* osl_Socket_ProtocolIpx */
107 NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
108 NSPROTO_SPXII, /* osl_Socket_ProtocolSpxII */
109 0 /* osl_Socket_ProtocolInvalid */
112 #define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
114 const sal_uInt32 TypeMap[]= {
115 SOCK_STREAM, /* osl_Socket_TypeStream */
116 SOCK_DGRAM, /* osl_Socket_TypeDgram */
117 SOCK_RAW, /* osl_Socket_TypeRaw */
118 SOCK_RDM, /* osl_Socket_TypeRdm */
119 SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */
120 0 /* osl_Socket_TypeInvalid */
123 static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType)
125 oslSocketType i= oslSocketType(0);
127 while(i != osl_Socket_TypeInvalid)
129 if(TypeMap[i] == nativeType)
130 return i;
131 i = static_cast<oslSocketType>(i + 1);
134 return i;
137 #define TYPE_TO_NATIVE(x) TypeMap[x]
138 #define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
140 const sal_uInt32 OptionMap[]= {
141 SO_DEBUG, /* osl_Socket_OptionDebug */
142 SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */
143 SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */
144 SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */
145 SO_DONTROUTE, /* osl_Socket_OptionDontRoute */
146 SO_BROADCAST, /* osl_Socket_OptionBroadcast */
147 SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */
148 SO_LINGER, /* osl_Socket_OptionLinger */
149 SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */
150 SO_SNDBUF, /* osl_Socket_OptionSndBuf */
151 SO_RCVBUF, /* osl_Socket_OptionRcvBuf */
152 SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */
153 SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */
154 SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */
155 SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */
156 SO_ERROR, /* osl_Socket_OptionError */
157 SO_TYPE, /* osl_Socket_OptionType */
158 TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */
159 0 /* osl_Socket_OptionInvalid */
162 #define OPTION_TO_NATIVE(x) OptionMap[x]
164 const sal_uInt32 OptionLevelMap[]= {
165 SOL_SOCKET, /* osl_Socket_LevelSocket */
166 IPPROTO_TCP, /* osl_Socket_LevelTcp */
167 0 /* osl_Socket_LevelInvalid */
170 #define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
172 const sal_uInt32 SocketMsgFlagMap[]= {
173 0, /* osl_Socket_MsgNormal */
174 MSG_OOB, /* osl_Socket_MsgOOB */
175 MSG_PEEK, /* osl_Socket_MsgPeek */
176 MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */
177 MSG_MAXIOVLEN, /* osl_Socket_MsgMaxIOVLen */
178 0 /* osl_Socket_MsgInvalid */
181 #define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
183 const sal_uInt32 SocketDirection[]= {
184 SD_RECEIVE, /* osl_Socket_DirRead */
185 SD_SEND, /* osl_Socket_DirWrite */
186 SD_BOTH, /* osl_Socket_DirReadWrite */
187 0 /* osl_Socket_DirInvalid */
190 #define DIRECTION_TO_NATIVE(x) SocketDirection[x]
192 const struct
194 int errcode;
195 oslSocketError error;
196 } SocketError[]= {
197 { 0, osl_Socket_E_None }, /* no error */
198 { ENOTSOCK, osl_Socket_E_NotSocket }, /* Socket operation on non-socket */
199 { EDESTADDRREQ, osl_Socket_E_DestAddrReq }, /* Destination address required */
200 { EMSGSIZE, osl_Socket_E_MsgSize }, /* Message too long */
201 { EPROTOTYPE, osl_Socket_E_Prototype }, /* Protocol wrong type for socket */
202 { ENOPROTOOPT, osl_Socket_E_NoProtocol }, /* Protocol not available */
203 { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */
204 #ifdef ESOCKTNOSUPPORT
205 { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport }, /* Socket type not supported */
206 #endif
207 { EOPNOTSUPP, osl_Socket_E_OpNotSupport }, /* Operation not supported on socket */
208 { EPFNOSUPPORT, osl_Socket_E_PfNoSupport }, /* Protocol family not supported */
209 { EAFNOSUPPORT, osl_Socket_E_AfNoSupport }, /* Address family not supported by
210 protocol family */
211 { EADDRINUSE, osl_Socket_E_AddrInUse }, /* Address already in use */
212 { EADDRNOTAVAIL, osl_Socket_E_AddrNotAvail }, /* Can't assign requested address */
213 { ENETDOWN, osl_Socket_E_NetDown }, /* Network is down */
214 { ENETUNREACH, osl_Socket_E_NetUnreachable }, /* Network is unreachable */
215 { ENETRESET, osl_Socket_E_NetReset }, /* Network dropped connection because
216 of reset */
217 { ECONNABORTED, osl_Socket_E_ConnAborted }, /* Software caused connection abort */
218 { ECONNRESET, osl_Socket_E_ConnReset }, /* Connection reset by peer */
219 { ENOBUFS, osl_Socket_E_NoBufferSpace }, /* No buffer space available */
220 { EISCONN, osl_Socket_E_IsConnected }, /* Socket is already connected */
221 { ENOTCONN, osl_Socket_E_NotConnected }, /* Socket is not connected */
222 { ESHUTDOWN, osl_Socket_E_Shutdown }, /* Can't send after socket shutdown */
223 #ifdef ETOOMANYREFS
224 { ETOOMANYREFS, osl_Socket_E_TooManyRefs }, /* Too many references: can't splice */
225 #endif
226 { ETIMEDOUT, osl_Socket_E_TimedOut }, /* Connection timed out */
227 { ECONNREFUSED, osl_Socket_E_ConnRefused }, /* Connection refused */
228 { EHOSTDOWN, osl_Socket_E_HostDown }, /* Host is down */
229 { EHOSTUNREACH, osl_Socket_E_HostUnreachable }, /* No route to host */
230 { EWOULDBLOCK, osl_Socket_E_WouldBlock }, /* call would block on non-blocking socket */
231 { EALREADY, osl_Socket_E_Already }, /* operation already in progress */
232 { EINPROGRESS, osl_Socket_E_InProgress }, /* operation now in progress */
233 { EAGAIN, osl_Socket_E_WouldBlock }, /* same as EWOULDBLOCK */
234 { -1, osl_Socket_E_InvalidError }
237 static oslSocketError osl_SocketErrorFromNative(int nativeType)
239 int i = 0;
241 while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
242 (SocketError[i].errcode != nativeType)) i++;
244 return SocketError[i].error;
247 #define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
249 static oslSocketAddr osl_psz_createInetSocketAddr (
250 const char* pszDottedAddr, sal_Int32 Port);
252 static oslHostAddr osl_psz_createHostAddr (
253 const char *pszHostname, const oslSocketAddr Addr);
255 static oslHostAddr osl_psz_createHostAddrByName (
256 const char *pszHostname);
258 static const char* osl_psz_getHostnameOfHostAddr (
259 const oslHostAddr Addr);
261 static oslSocketAddr osl_psz_resolveHostname (
262 const char* pszHostname);
264 static sal_Int32 osl_psz_getServicePort (
265 const char* pszServicename, const char* pszProtocol);
267 static void osl_psz_getLastSocketErrorDescription (
268 oslSocket Socket, char* pBuffer, sal_uInt32 BufferSize);
270 namespace {
272 int convertToMs(TimeValue const * value) {
273 return value->Seconds * 1000 + value->Nanosec / 1000000; //TODO: overflow
278 static oslSocket createSocketImpl()
280 oslSocket pSocket;
282 pSocket = static_cast<oslSocket>(calloc(1, sizeof(struct oslSocketImpl)));
284 pSocket->m_Socket = OSL_INVALID_SOCKET;
285 pSocket->m_nLastError = 0;
286 pSocket->m_nRefCount = 1;
288 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
289 pSocket->m_bIsAccepting = false;
290 #endif
292 return pSocket;
295 static void destroySocketImpl(oslSocket Socket)
297 if ( Socket != nullptr)
298 free(Socket);
301 static oslSocketAddr createSocketAddr()
303 oslSocketAddr pAddr = static_cast<oslSocketAddr>(rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl )));
304 return pAddr;
307 static oslSocketAddr createSocketAddrWithFamily(
308 oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
310 oslSocketAddr pAddr;
312 SAL_WARN_IF( family != osl_Socket_FamilyInet, "sal.osl", "creating socket for non-IP address family" );
314 pAddr = createSocketAddr();
315 switch( family )
317 case osl_Socket_FamilyInet:
319 struct sockaddr_in* pInetAddr= reinterpret_cast<sockaddr_in*>(&pAddr->m_sockaddr);
321 pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
322 pInetAddr->sin_addr.s_addr = nAddr;
323 pInetAddr->sin_port = static_cast<sal_uInt16>(port&0xffff);
324 break;
326 default:
327 pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
329 return pAddr;
332 static oslSocketAddr createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
334 oslSocketAddr pAddr = createSocketAddr();
335 memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) );
336 return pAddr;
339 static void destroySocketAddr( oslSocketAddr addr )
341 free( addr );
344 oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
346 oslSocketAddr pAddr = nullptr;
348 /* is it an internet-Addr? */
349 if (Family == osl_Socket_FamilyInet)
351 pAddr = createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
353 else
355 pAddr = createSocketAddrWithFamily( Family , 0 , 0 );
358 return pAddr;
361 oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
363 oslSocketAddr pCopy = nullptr;
364 if (Addr)
366 pCopy = createSocketAddr();
368 if (pCopy)
369 memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
371 return pCopy;
374 sal_Bool SAL_CALL osl_isEqualSocketAddr (
375 oslSocketAddr Addr1,
376 oslSocketAddr Addr2)
378 struct sockaddr* pAddr1 = nullptr;
379 struct sockaddr* pAddr2 = nullptr;
381 assert(Addr1 && Addr2);
382 pAddr1 = &(Addr1->m_sockaddr);
383 pAddr2 = &(Addr2->m_sockaddr);
385 if (pAddr1 == pAddr2)
387 return true;
390 if (pAddr1->sa_family == pAddr2->sa_family)
392 switch (pAddr1->sa_family)
394 case AF_INET:
396 struct sockaddr_in* pInetAddr1= reinterpret_cast<sockaddr_in*>(pAddr1);
397 struct sockaddr_in* pInetAddr2= reinterpret_cast<sockaddr_in*>(pAddr2);
399 if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
400 (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
401 (pInetAddr1->sin_port == pInetAddr2->sin_port))
402 return true;
403 [[fallthrough]];
406 default:
408 return (memcmp(pAddr1, pAddr2, sizeof(struct sockaddr)) == 0);
413 return false;
416 oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
417 rtl_uString *strDottedAddr,
418 sal_Int32 Port)
420 sal_uInt32 nAddr = OSL_INADDR_NONE;
421 oslSocketAddr pAddr;
423 if (strDottedAddr && strDottedAddr->length)
425 /* Dotted host address for limited broadcast */
426 rtl_String *pDottedAddr = nullptr;
428 rtl_uString2String (
429 &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
430 RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
432 in_addr buf;
433 if (inet_pton (AF_INET, pDottedAddr->buffer, &buf) == 1) {
434 nAddr = buf.s_addr;
436 rtl_string_release (pDottedAddr);
439 if (nAddr != OSL_INADDR_NONE)
441 /* Limited broadcast */
442 nAddr = ntohl(nAddr);
443 if (IN_CLASSA(nAddr))
445 nAddr &= IN_CLASSA_NET;
446 nAddr |= IN_CLASSA_HOST;
448 else if (IN_CLASSB(nAddr))
450 nAddr &= IN_CLASSB_NET;
451 nAddr |= IN_CLASSB_HOST;
453 else if (IN_CLASSC(nAddr))
455 nAddr &= IN_CLASSC_NET;
456 nAddr |= IN_CLASSC_HOST;
458 else
460 /* No broadcast in class D */
461 return nullptr;
463 nAddr = htonl(nAddr);
466 pAddr = createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
467 return pAddr;
470 oslSocketAddr SAL_CALL osl_createInetSocketAddr (
471 rtl_uString *ustrDottedAddr,
472 sal_Int32 Port)
474 rtl_String* strDottedAddr=nullptr;
475 oslSocketAddr Addr;
476 char* pszDottedAddr=nullptr;
478 if ( ustrDottedAddr != nullptr )
480 rtl_uString2String( &strDottedAddr,
481 rtl_uString_getStr(ustrDottedAddr),
482 rtl_uString_getLength(ustrDottedAddr),
483 RTL_TEXTENCODING_UTF8,
484 OUSTRING_TO_OSTRING_CVTFLAGS);
485 pszDottedAddr = rtl_string_getStr(strDottedAddr);
488 Addr = pszDottedAddr ? osl_psz_createInetSocketAddr(pszDottedAddr, Port) : nullptr;
490 if ( strDottedAddr != nullptr )
492 rtl_string_release(strDottedAddr);
495 return Addr;
498 oslSocketAddr osl_psz_createInetSocketAddr (
499 const char* pszDottedAddr,
500 sal_Int32 Port)
502 oslSocketAddr pAddr = nullptr;
503 in_addr buf;
504 if(inet_pton(AF_INET, pszDottedAddr, &buf) == 1)
506 /* valid dotted addr */
507 pAddr = createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , buf.s_addr );
509 return pAddr;
512 oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
514 oslSocketResult res = osl_Socket_Error;
516 SAL_WARN_IF( !pAddr, "sal.osl", "setting address of undefined socket address" );
517 SAL_WARN_IF( !pByteSeq, "sal.osl", "setting undefined address for socket address" );
519 if( pAddr && pByteSeq )
521 struct sockaddr_in * pSystemInetAddr;
523 assert( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
524 assert( pByteSeq->nElements == 4 );
526 pSystemInetAddr = reinterpret_cast<sockaddr_in *>(&pAddr->m_sockaddr);
527 memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
528 res = osl_Socket_Ok;
530 return res;
533 oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
535 oslSocketResult res = osl_Socket_Error;
537 SAL_WARN_IF( !pAddr, "sal.osl", "getting address of undefined socket address" );
538 SAL_WARN_IF( !ppByteSeq, "sal.osl", "getting address to undefined address pointer" );
540 if( pAddr && ppByteSeq )
542 struct sockaddr_in * pSystemInetAddr = reinterpret_cast<sockaddr_in *>(&pAddr->m_sockaddr);
543 rtl_byte_sequence_constructFromArray( ppByteSeq, reinterpret_cast<sal_Int8 *>(&pSystemInetAddr->sin_addr), 4);
544 res = osl_Socket_Ok;
546 return res;
549 /** try to figure out a full-qualified hostname, by adding the current domain
550 as given by the domainname program to the given hostname.
551 This function MUST NOT call gethostbyname since pHostName already points
552 to data returned by gethostname and would be garbled: use gethostname_r
553 instead!
556 namespace {
558 struct oslAddrInfo
560 addrinfo* pAddrInfoList = nullptr;
561 int nError;
563 oslAddrInfo(const char* name, bool isInet = false)
565 addrinfo aHints;
566 memset(&aHints, 0, sizeof(addrinfo));
567 if (isInet)
568 aHints.ai_family = AF_INET;
569 aHints.ai_flags = AI_CANONNAME;
571 nError = getaddrinfo(name, nullptr, &aHints, &pAddrInfoList);
574 ~oslAddrInfo()
576 if (nError == 0)
577 freeaddrinfo(pAddrInfoList);
580 const char* getHostName() const
582 assert(pAddrInfoList);
583 return pAddrInfoList->ai_canonname;
588 static bool isFullQualifiedDomainName (const char *pHostName)
590 /* a FQDN (aka 'hostname.domain.top_level_domain' )
591 * is a name which contains a dot '.' in it ( would
592 * match as well for 'hostname.' but is good enough
593 * for now )*/
594 return strchr( pHostName, int('.') ) != nullptr;
597 static char* getFullQualifiedDomainName (const char *pHostName)
599 char *pFullQualifiedName = nullptr;
601 if (isFullQualifiedDomainName(pHostName))
603 pFullQualifiedName = strdup(pHostName);
605 else
607 oslAddrInfo aAddrInfo(pHostName);
608 if (aAddrInfo.nError == 0)
609 pFullQualifiedName = strdup(aAddrInfo.getHostName());
612 return pFullQualifiedName;
615 struct oslHostAddrImpl
617 char *pHostName;
618 oslSocketAddr pSockAddr;
621 static oslHostAddr addrinfoToHostAddr (const addrinfo* ai)
623 if (!ai || !ai->ai_canonname || !ai->ai_addr)
624 return nullptr;
626 char* cn = getFullQualifiedDomainName(ai->ai_canonname);
627 SAL_WARN_IF( !cn, "sal.osl", "couldn't get full qualified domain name" );
628 if (cn == nullptr)
629 return nullptr;
631 oslSocketAddr pSockAddr = createSocketAddr();
632 SAL_WARN_IF( !pSockAddr, "sal.osl", "insufficient memory" );
633 if (pSockAddr == nullptr)
635 free(cn);
636 return nullptr;
639 if (ai->ai_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
641 memcpy (
642 &(pSockAddr->m_sockaddr),
643 ai->ai_addr,
644 ai->ai_addrlen);
646 else
648 /* unknown address family */
649 /* future extensions for new families might be implemented here */
651 SAL_WARN( "sal.osl", "unknown address family" );
653 destroySocketAddr( pSockAddr );
654 free (cn);
655 return nullptr;
658 oslHostAddr pAddr = static_cast<oslHostAddr>(malloc(sizeof(struct oslHostAddrImpl)));
659 SAL_WARN_IF( !pAddr, "sal.osl", "allocation error" );
660 if (pAddr == nullptr)
662 destroySocketAddr( pSockAddr );
663 free (cn);
664 return nullptr;
667 pAddr->pHostName= cn;
668 pAddr->pSockAddr= pSockAddr;
670 return pAddr;
673 oslHostAddr SAL_CALL osl_createHostAddr (
674 rtl_uString *ustrHostname,
675 const oslSocketAddr Addr)
677 oslHostAddr HostAddr;
678 rtl_String* strHostname=nullptr;
679 char* pszHostName=nullptr;
681 if ( ustrHostname != nullptr )
683 rtl_uString2String( &strHostname,
684 rtl_uString_getStr(ustrHostname),
685 rtl_uString_getLength(ustrHostname),
686 RTL_TEXTENCODING_UTF8,
687 OUSTRING_TO_OSTRING_CVTFLAGS );
688 pszHostName = rtl_string_getStr(strHostname);
691 HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
693 if ( strHostname != nullptr )
695 rtl_string_release(strHostname);
698 return HostAddr;
701 oslHostAddr osl_psz_createHostAddr (
702 const char *pszHostname,
703 const oslSocketAddr pAddr)
705 oslHostAddr pHostAddr;
706 char *cn;
708 SAL_WARN_IF( !pszHostname, "sal.osl", "undefined hostname" );
709 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
710 if ((pszHostname == nullptr) || (pAddr == nullptr))
711 return nullptr;
713 cn = strdup(pszHostname);
714 SAL_WARN_IF( !cn, "sal.osl", "insufficient memory" );
715 if (cn == nullptr)
716 return nullptr;
718 pHostAddr= static_cast<oslHostAddr>(malloc(sizeof(struct oslHostAddrImpl)));
719 SAL_WARN_IF( !pHostAddr, "sal.osl", "allocation error" );
720 if (pHostAddr == nullptr)
722 free (cn);
723 return nullptr;
726 pHostAddr->pHostName= cn;
727 pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
729 return pHostAddr;
732 oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
734 oslHostAddr HostAddr;
735 rtl_String* strHostname=nullptr;
736 char* pszHostName=nullptr;
738 if ( ustrHostname != nullptr )
740 rtl_uString2String( &strHostname,
741 rtl_uString_getStr(ustrHostname),
742 rtl_uString_getLength(ustrHostname),
743 RTL_TEXTENCODING_UTF8,
744 OUSTRING_TO_OSTRING_CVTFLAGS );
745 pszHostName=rtl_string_getStr(strHostname);
748 HostAddr = osl_psz_createHostAddrByName(pszHostName);
750 if ( strHostname != nullptr )
752 rtl_string_release(strHostname);
755 return HostAddr;
758 oslHostAddr osl_psz_createHostAddrByName (const char *pszHostname)
760 oslAddrInfo aAddrInfo(pszHostname, /* isInet */ true);
762 return addrinfoToHostAddr (aAddrInfo.pAddrInfoList);
765 oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
767 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
769 if (pAddr == nullptr)
770 return nullptr;
772 if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
774 const struct sockaddr_in *sin = reinterpret_cast<sockaddr_in *>(&pAddr->m_sockaddr);
775 if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
776 return nullptr;
778 char host[MAX_HOSTBUFFER_SIZE];
779 int res = getnameinfo(&pAddr->m_sockaddr, sizeof(struct sockaddr_in),
780 host, sizeof(host), nullptr, 0, NI_NAMEREQD);
781 if (res != 0)
782 return nullptr;
784 char *cn = getFullQualifiedDomainName(host);
785 SAL_WARN_IF( !cn, "sal.osl", "couldn't get full qualified domain name" );
786 if (cn == nullptr)
787 return nullptr;
789 oslSocketAddr pSockAddr = createSocketAddr();
790 SAL_WARN_IF( !pSockAddr, "sal.osl", "insufficient memory" );
791 if (pSockAddr == nullptr)
793 free(cn);
794 return nullptr;
797 memcpy(&pSockAddr->m_sockaddr, &pAddr->m_sockaddr, sizeof(pAddr->m_sockaddr));
799 oslHostAddr pHostAddr = static_cast<oslHostAddr>(malloc(sizeof(struct oslHostAddrImpl)));
800 SAL_WARN_IF( !pAddr, "sal.osl", "allocation error" );
801 if (pHostAddr == nullptr)
803 destroySocketAddr(pSockAddr);
804 free(cn);
805 return nullptr;
808 pHostAddr->pHostName = cn;
809 pHostAddr->pSockAddr = pSockAddr;
811 return pHostAddr;
814 return nullptr;
817 oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr)
819 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
821 if (pAddr)
822 return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
823 return nullptr;
826 void SAL_CALL osl_getHostnameOfHostAddr (
827 const oslHostAddr Addr,
828 rtl_uString **ustrHostname)
830 const char* pHostname = osl_psz_getHostnameOfHostAddr(Addr);
832 rtl_uString_newFromAscii (ustrHostname, pHostname);
835 const char* osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
837 if (pAddr)
838 return pAddr->pHostName;
839 return nullptr;
842 oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
844 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
846 if (pAddr)
847 return pAddr->pSockAddr;
848 return nullptr;
851 void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
853 if (pAddr)
855 if (pAddr->pHostName)
856 free (pAddr->pHostName);
857 if (pAddr->pSockAddr)
858 osl_destroySocketAddr (pAddr->pSockAddr);
859 free (pAddr);
863 namespace
865 oslSocketResult lcl_getLocalHostname(rtl_uString **ustrLocalHostname, bool bUseFQDN)
867 static auto const init = [bUseFQDN]() -> std::pair<oslSocketResult, OUString> {
868 char LocalHostname[256] = "";
870 #ifdef SYSV
871 struct utsname uts;
873 if (uname(&uts) < 0)
874 return {osl_Socket_Error, OUString()};
876 if ((strlen(uts.nodename) + 1) > nBufLen)
877 return {osl_Socket_Error, OUString()};
879 strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
880 #else /* BSD compatible */
881 if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
882 return {osl_Socket_Error, OUString()};
883 #endif /* SYSV */
884 LocalHostname[sizeof(LocalHostname)-1] = 0;
886 /* check if we have an FQDN */
887 if (bUseFQDN && strchr(LocalHostname, '.') == nullptr)
889 oslHostAddr Addr;
891 /* no, determine it via dns */
892 Addr = osl_psz_createHostAddrByName(LocalHostname);
894 const char *pStr;
895 if ((pStr = osl_psz_getHostnameOfHostAddr(Addr)) != nullptr)
897 strncpy(LocalHostname, pStr, sizeof( LocalHostname ));
898 LocalHostname[sizeof(LocalHostname)-1] = 0;
900 osl_destroyHostAddr(Addr);
903 if (LocalHostname[0] != '\0')
905 return {osl_Socket_Ok, OUString::createFromAscii(LocalHostname)};
908 return {osl_Socket_Error, OUString()};
909 }();
911 rtl_uString_assign(ustrLocalHostname,init.second.pData);
913 return init.first;
917 oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
919 return lcl_getLocalHostname(ustrLocalHostname, false);
922 oslSocketResult osl_getLocalHostnameFQDN(rtl_uString **ustrLocalHostname)
924 return lcl_getLocalHostname(ustrLocalHostname, true);
927 oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
929 oslSocketAddr Addr;
930 rtl_String* strHostname=nullptr;
931 char* pszHostName=nullptr;
933 if ( ustrHostname != nullptr )
935 rtl_uString2String( &strHostname,
936 rtl_uString_getStr(ustrHostname),
937 rtl_uString_getLength(ustrHostname),
938 RTL_TEXTENCODING_UTF8,
939 OUSTRING_TO_OSTRING_CVTFLAGS );
940 pszHostName = rtl_string_getStr(strHostname);
943 Addr = osl_psz_resolveHostname(pszHostName);
945 if ( strHostname != nullptr )
947 rtl_string_release(strHostname);
950 return Addr;
953 oslSocketAddr osl_psz_resolveHostname(const char* pszHostname)
955 struct oslHostAddrImpl *pAddr = osl_psz_createHostAddrByName(pszHostname);
957 if (pAddr)
959 oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr);
961 osl_destroyHostAddr(pAddr);
963 return SockAddr;
966 return nullptr;
969 sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol)
971 sal_Int32 nPort;
972 rtl_String* strServicename=nullptr;
973 rtl_String* strProtocol=nullptr;
974 char* pszServiceName=nullptr;
975 char* pszProtocol=nullptr;
977 if ( ustrServicename != nullptr )
979 rtl_uString2String( &strServicename,
980 rtl_uString_getStr(ustrServicename),
981 rtl_uString_getLength(ustrServicename),
982 RTL_TEXTENCODING_UTF8,
983 OUSTRING_TO_OSTRING_CVTFLAGS );
984 pszServiceName = rtl_string_getStr(strServicename);
987 if ( ustrProtocol != nullptr )
989 rtl_uString2String( &strProtocol,
990 rtl_uString_getStr(ustrProtocol),
991 rtl_uString_getLength(ustrProtocol),
992 RTL_TEXTENCODING_UTF8,
993 OUSTRING_TO_OSTRING_CVTFLAGS );
994 pszProtocol = rtl_string_getStr(strProtocol);
997 nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
999 if ( strServicename != nullptr )
1001 rtl_string_release(strServicename);
1004 if ( strProtocol != nullptr )
1006 rtl_string_release(strProtocol);
1009 return nPort;
1012 sal_Int32 osl_psz_getServicePort(const char* pszServicename,
1013 const char* pszProtocol)
1015 struct servent* ps;
1017 ps= getservbyname(pszServicename, pszProtocol);
1019 if (ps != nullptr)
1020 return ntohs(ps->s_port);
1022 return OSL_INVALID_PORT;
1025 void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
1027 destroySocketAddr( pAddr );
1030 oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
1032 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1034 if (pAddr)
1035 return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
1036 return osl_Socket_FamilyInvalid;
1039 sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
1041 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1043 if( pAddr )
1045 struct sockaddr_in* pSystemInetAddr= reinterpret_cast<sockaddr_in*>(&pAddr->m_sockaddr);
1047 if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1048 return ntohs(pSystemInetAddr->sin_port);
1050 return OSL_INVALID_PORT;
1053 sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port)
1055 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1057 if( pAddr )
1059 struct sockaddr_in* pSystemInetAddr= reinterpret_cast<sockaddr_in*>(&pAddr->m_sockaddr);
1060 if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1062 pSystemInetAddr->sin_port= htons(static_cast<short>(Port));
1063 return true;
1067 /* this is not a inet-addr => can't set port */
1068 return false;
1071 oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
1073 oslHostAddr pHostAddr= osl_createHostAddrByAddr(Addr);
1075 if (!pHostAddr)
1077 return osl_Socket_Error;
1080 rtl_uString_newFromAscii(ustrHostname,pHostAddr->pHostName);
1082 osl_destroyHostAddr(pHostAddr);
1084 return osl_Socket_Ok;
1087 oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
1089 if( !Addr )
1091 return osl_Socket_Error;
1094 struct sockaddr_in* pSystemInetAddr = reinterpret_cast<sockaddr_in *>(&Addr->m_sockaddr);
1096 if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1098 return osl_Socket_Error;
1101 char buf[INET_ADDRSTRLEN];
1102 auto const text = inet_ntop(AF_INET, &pSystemInetAddr->sin_addr, buf, INET_ADDRSTRLEN);
1103 assert(text != nullptr);
1104 rtl_uString_newFromAscii(ustrDottedInetAddr,text);
1106 return osl_Socket_Ok;
1110 oslSocket SAL_CALL osl_createSocket(
1111 oslAddrFamily Family,
1112 oslSocketType Type,
1113 oslProtocol Protocol)
1115 oslSocket pSocket;
1117 /* alloc memory */
1118 pSocket= createSocketImpl();
1120 /* create socket */
1121 pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
1122 TYPE_TO_NATIVE(Type),
1123 PROTOCOL_TO_NATIVE(Protocol));
1125 /* creation failed => free memory */
1126 if(pSocket->m_Socket == OSL_INVALID_SOCKET)
1128 int nErrno = errno;
1129 SAL_WARN( "sal.osl", "socket creation failed: " << UnixErrnoString(nErrno) );
1131 destroySocketImpl(pSocket);
1132 pSocket= nullptr;
1134 else
1136 sal_Int32 nFlags=0;
1137 /* set close-on-exec flag */
1138 if ((nFlags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
1140 nFlags |= FD_CLOEXEC;
1141 if (fcntl(pSocket->m_Socket, F_SETFD, nFlags) == -1)
1143 pSocket->m_nLastError=errno;
1144 int nErrno = errno;
1145 SAL_WARN( "sal.osl", "failed changing socket flags: " << UnixErrnoString(nErrno) );
1148 else
1150 pSocket->m_nLastError=errno;
1154 return pSocket;
1157 void SAL_CALL osl_acquireSocket(oslSocket pSocket)
1159 osl_atomic_increment(&(pSocket->m_nRefCount));
1162 void SAL_CALL osl_releaseSocket(oslSocket pSocket)
1164 if (pSocket && osl_atomic_decrement(&(pSocket->m_nRefCount)) == 0)
1166 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1167 if (pSocket->m_bIsAccepting)
1169 SAL_WARN( "sal.osl", "attempt to destroy socket while accepting" );
1170 return;
1172 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1173 osl_closeSocket(pSocket);
1174 destroySocketImpl(pSocket);
1178 void SAL_CALL osl_closeSocket(oslSocket pSocket)
1180 /* socket already invalid */
1181 if (!pSocket)
1182 return;
1184 pSocket->m_nLastError=0;
1185 sal_Int32 nFD = pSocket->m_Socket;
1187 if (nFD == OSL_INVALID_SOCKET)
1188 return;
1190 pSocket->m_Socket = OSL_INVALID_SOCKET;
1192 sal_Int32 nRet=0;
1193 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1194 pSocket->m_bIsInShutdown = true;
1196 if (pSocket->m_bIsAccepting)
1198 union {
1199 struct sockaddr aSockAddr;
1200 struct sockaddr_in aSockAddrIn;
1201 } s;
1202 socklen_t nSockLen = sizeof(s.aSockAddr);
1204 nRet = getsockname(nFD, &s.aSockAddr, &nSockLen);
1205 if (nRet < 0)
1207 int nErrno = errno;
1208 SAL_WARN( "sal.osl", "getsockname call failed: " << UnixErrnoString(nErrno) );
1211 if (s.aSockAddr.sa_family == AF_INET)
1213 if (s.aSockAddrIn.sin_addr.s_addr == htonl(INADDR_ANY))
1215 s.aSockAddrIn.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1218 int nConnFD = socket(AF_INET, SOCK_STREAM, 0);
1219 if (nConnFD < 0)
1221 int nErrno = errno;
1222 SAL_WARN( "sal.osl", "socket call failed: " << UnixErrnoString(nErrno) );
1224 else
1226 nRet = connect(nConnFD, &s.aSockAddr, sizeof(s.aSockAddr));
1227 if (nRet < 0)
1229 int nErrno = errno;
1230 SAL_WARN( "sal.osl", "connect call failed: " << UnixErrnoString(nErrno) );
1232 close(nConnFD);
1235 pSocket->m_bIsAccepting = false;
1237 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1239 nRet=close(nFD);
1240 if (nRet != 0)
1242 pSocket->m_nLastError=errno;
1243 int nErrno = errno;
1244 SAL_WARN( "sal.osl", "closeSocket close failed: " << UnixErrnoString(nErrno) );
1247 pSocket->m_Socket = OSL_INVALID_SOCKET;
1250 /* Note from function creator: I rely on the fact that oslSocketAddr and struct sockaddr
1251 are the same! I don't like it very much but see no other easy way to conceal
1252 the struct sockaddr from the eyes of the user. */
1253 oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
1255 socklen_t AddrLen;
1256 struct sockaddr Addr;
1257 oslSocketAddr pAddr;
1259 if (pSocket == nullptr) /* ENOTSOCK */
1260 return nullptr;
1262 AddrLen= sizeof(struct sockaddr);
1264 if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1265 return nullptr;
1267 pAddr = createSocketAddrFromSystem( &Addr );
1268 return pAddr;
1271 oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
1273 socklen_t AddrLen;
1274 struct sockaddr Addr;
1276 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1277 if ( pSocket == nullptr )
1279 return nullptr;
1282 pSocket->m_nLastError=0;
1283 AddrLen= sizeof(struct sockaddr);
1285 if(getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1287 pSocket->m_nLastError=errno;
1288 return nullptr;
1290 return createSocketAddrFromSystem( &Addr );
1293 sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
1294 oslSocketAddr pAddr)
1296 int nRet;
1298 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1299 SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1300 if ( pSocket == nullptr || pAddr == nullptr )
1302 return false;
1305 pSocket->m_nLastError=0;
1307 nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
1309 if ( nRet == OSL_SOCKET_ERROR)
1311 pSocket->m_nLastError=errno;
1312 return false;
1315 return true;
1318 sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
1319 sal_Int32 MaxPendingConnections)
1321 int nRet;
1323 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1324 if ( pSocket == nullptr )
1326 return false;
1329 pSocket->m_nLastError=0;
1331 nRet = listen(pSocket->m_Socket,
1332 MaxPendingConnections == -1 ?
1333 SOMAXCONN :
1334 MaxPendingConnections);
1335 if ( nRet == OSL_SOCKET_ERROR)
1337 pSocket->m_nLastError=errno;
1338 return false;
1341 return true;
1344 oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
1345 oslSocketAddr pAddr,
1346 const TimeValue* pTimeout)
1348 int ReadyHandles;
1350 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1352 if ( pSocket == nullptr )
1354 return osl_Socket_Error;
1357 pSocket->m_nLastError=0;
1359 if (osl_isNonBlockingMode(pSocket))
1361 if (connect(pSocket->m_Socket,
1362 &(pAddr->m_sockaddr),
1363 sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1364 return osl_Socket_Ok;
1366 if (errno == EWOULDBLOCK || errno == EINPROGRESS)
1368 pSocket->m_nLastError=EINPROGRESS;
1369 return osl_Socket_InProgress;
1372 pSocket->m_nLastError=errno;
1373 int nErrno = errno;
1374 SAL_WARN( "sal.osl", "connection failed: " << UnixErrnoString(nErrno) );
1375 return osl_Socket_Error;
1378 /* set socket temporarily to non-blocking */
1379 if( !osl_enableNonBlockingMode(pSocket, true) )
1380 SAL_WARN( "sal.osl", "failed to enable non-blocking mode" );
1382 /* initiate connect */
1383 if(connect(pSocket->m_Socket,
1384 &(pAddr->m_sockaddr),
1385 sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1387 /* immediate connection */
1388 osl_enableNonBlockingMode(pSocket, false);
1390 return osl_Socket_Ok;
1393 /* really an error or just delayed? */
1394 if (errno != EINPROGRESS)
1396 pSocket->m_nLastError=errno;
1397 int nErrno = errno;
1398 SAL_WARN( "sal.osl", "connection failed: " << UnixErrnoString(nErrno) );
1400 osl_enableNonBlockingMode(pSocket, false);
1401 return osl_Socket_Error;
1404 /* prepare poll set for socket */
1405 pollfd Set = {pSocket->m_Socket, POLLPRI | POLLOUT, 0};
1407 /* poll */
1408 ReadyHandles= poll(&Set, 1,
1409 pTimeout ? convertToMs(pTimeout) : -1);
1411 if (ReadyHandles > 0) /* connected */
1413 if ( (Set.revents & POLLOUT) != 0 )
1415 int nErrorCode = 0;
1416 socklen_t nErrorSize = sizeof( nErrorCode );
1418 int nSockOpt;
1420 nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
1421 &nErrorCode, &nErrorSize );
1422 if ( (nSockOpt == 0) && (nErrorCode == 0))
1424 osl_enableNonBlockingMode(pSocket, false);
1425 return osl_Socket_Ok;
1427 else
1429 pSocket->m_nLastError = (nSockOpt == 0) ? nErrorCode : errno;
1430 return osl_Socket_Error;
1433 else
1435 return osl_Socket_Error;
1438 else if (ReadyHandles < 0) /* error */
1440 if (errno == EBADF) /* most probably interrupted by close() */
1442 /* do not access pSockImpl because it is about to be or */
1443 /* already destroyed */
1444 return osl_Socket_Interrupted;
1446 pSocket->m_nLastError=errno;
1447 return osl_Socket_Error;
1449 else /* timeout */
1451 pSocket->m_nLastError=errno;
1452 return osl_Socket_TimedOut;
1456 oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
1457 oslSocketAddr* ppAddr)
1459 struct sockaddr Addr;
1460 int Connection, Flags;
1461 oslSocket pConnectionSockImpl;
1463 socklen_t AddrLen = sizeof(struct sockaddr);
1464 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1465 if ( pSocket == nullptr )
1467 return nullptr;
1470 pSocket->m_nLastError=0;
1471 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1472 pSocket->m_bIsAccepting = true;
1473 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1475 if( ppAddr && *ppAddr )
1477 osl_destroySocketAddr( *ppAddr );
1478 *ppAddr = nullptr;
1481 /* prevent Linux EINTR behaviour */
1484 Connection = accept(pSocket->m_Socket, &Addr, &AddrLen);
1485 } while (Connection == -1 && errno == EINTR);
1487 /* accept failed? */
1488 if( Connection == OSL_SOCKET_ERROR )
1490 pSocket->m_nLastError=errno;
1491 int nErrno = errno;
1492 SAL_WARN( "sal.osl", "accept connection failed: " << UnixErrnoString(nErrno) );
1494 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1495 pSocket->m_bIsAccepting = false;
1496 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1497 return nullptr;
1500 assert(AddrLen == sizeof(struct sockaddr));
1502 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1503 if ( pSocket->m_bIsInShutdown )
1505 close(Connection);
1506 SAL_WARN( "sal.osl", "close while accept" );
1507 return nullptr;
1509 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1511 if(ppAddr)
1513 *ppAddr= createSocketAddrFromSystem(&Addr);
1516 /* alloc memory */
1517 pConnectionSockImpl= createSocketImpl();
1519 /* set close-on-exec flag */
1520 if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
1522 Flags |= FD_CLOEXEC;
1523 if (fcntl(Connection, F_SETFD, Flags) == -1)
1525 pSocket->m_nLastError=errno;
1526 int nErrno = errno;
1527 SAL_WARN( "sal.osl", "fcntl failed: " << UnixErrnoString(nErrno) );
1532 pConnectionSockImpl->m_Socket = Connection;
1533 pConnectionSockImpl->m_nLastError = 0;
1534 #if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1535 pConnectionSockImpl->m_bIsAccepting = false;
1537 pSocket->m_bIsAccepting = false;
1538 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1539 return pConnectionSockImpl;
1542 sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
1543 void* pBuffer,
1544 sal_uInt32 BytesToRead,
1545 oslSocketMsgFlag Flag)
1547 int nRead;
1549 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1550 if ( pSocket == nullptr )
1552 return -1;
1555 pSocket->m_nLastError=0;
1559 nRead = recv(pSocket->m_Socket,
1560 pBuffer,
1561 BytesToRead,
1562 MSG_FLAG_TO_NATIVE(Flag));
1563 } while ( nRead < 0 && errno == EINTR );
1565 if ( nRead < 0 )
1567 pSocket->m_nLastError=errno;
1568 int nErrno = errno;
1569 SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: " << UnixErrnoString(nErrno) );
1571 else if ( nRead == 0 )
1573 SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: EOL" );
1576 return nRead;
1579 sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
1580 oslSocketAddr pSenderAddr,
1581 void* pBuffer,
1582 sal_uInt32 BufferSize,
1583 oslSocketMsgFlag Flag)
1585 int nRead;
1586 struct sockaddr *pSystemSockAddr = nullptr;
1587 socklen_t AddrLen = 0;
1588 if( pSenderAddr )
1590 AddrLen = sizeof( struct sockaddr );
1591 pSystemSockAddr = &(pSenderAddr->m_sockaddr);
1594 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1595 if ( pSocket == nullptr )
1597 return -1;
1600 pSocket->m_nLastError=0;
1602 nRead = recvfrom(pSocket->m_Socket,
1603 pBuffer,
1604 BufferSize,
1605 MSG_FLAG_TO_NATIVE(Flag),
1606 pSystemSockAddr,
1607 &AddrLen);
1609 if ( nRead < 0 )
1611 pSocket->m_nLastError=errno;
1612 int nErrno = errno;
1613 SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: " << UnixErrnoString(nErrno) );
1615 else if ( nRead == 0 )
1617 SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: EOL" );
1620 return nRead;
1623 sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
1624 const void* pBuffer,
1625 sal_uInt32 BytesToSend,
1626 oslSocketMsgFlag Flag)
1628 int nWritten;
1630 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1631 if ( pSocket == nullptr )
1633 return -1;
1636 pSocket->m_nLastError=0;
1640 nWritten = send(pSocket->m_Socket,
1641 pBuffer,
1642 BytesToSend,
1643 MSG_FLAG_TO_NATIVE(Flag));
1644 } while ( nWritten < 0 && errno == EINTR );
1646 if ( nWritten < 0 )
1648 pSocket->m_nLastError=errno;
1649 int nErrno = errno;
1650 SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: " << UnixErrnoString(nErrno) );
1652 else if ( nWritten == 0 )
1654 SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: EOL" );
1657 return nWritten;
1660 sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
1661 oslSocketAddr ReceiverAddr,
1662 const void* pBuffer,
1663 sal_uInt32 BytesToSend,
1664 oslSocketMsgFlag Flag)
1666 int nWritten;
1668 struct sockaddr *pSystemSockAddr = nullptr;
1669 int AddrLen = 0;
1670 if( ReceiverAddr )
1672 pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
1673 AddrLen = sizeof( struct sockaddr );
1676 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1677 if ( pSocket == nullptr )
1679 return -1;
1682 pSocket->m_nLastError=0;
1684 /* ReceiverAddr might be 0 when used on a connected socket. */
1685 /* Then sendto should behave like send. */
1687 nWritten = sendto(pSocket->m_Socket,
1688 pBuffer,
1689 BytesToSend,
1690 MSG_FLAG_TO_NATIVE(Flag),
1691 pSystemSockAddr,
1692 AddrLen);
1694 if ( nWritten < 0 )
1696 pSocket->m_nLastError=errno;
1697 int nErrno = errno;
1698 SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: " << UnixErrnoString(nErrno) );
1700 else if ( nWritten == 0 )
1702 SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: EOL" );
1705 return nWritten;
1708 sal_Int32 SAL_CALL osl_readSocket (
1709 oslSocket pSocket, void *pBuffer, sal_Int32 n )
1711 sal_uInt8 * Ptr = static_cast<sal_uInt8 *>(pBuffer);
1712 sal_uInt32 BytesRead= 0;
1713 sal_uInt32 BytesToRead= n;
1715 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1717 /* loop until all desired bytes were read or an error occurred */
1718 while (BytesToRead > 0)
1720 sal_Int32 RetVal;
1721 RetVal= osl_receiveSocket(pSocket,
1722 Ptr,
1723 BytesToRead,
1724 osl_Socket_MsgNormal);
1726 /* error occurred? */
1727 if(RetVal <= 0)
1729 break;
1732 BytesToRead -= RetVal;
1733 BytesRead += RetVal;
1734 Ptr += RetVal;
1737 return BytesRead;
1740 sal_Int32 SAL_CALL osl_writeSocket(
1741 oslSocket pSocket, const void *pBuffer, sal_Int32 n )
1743 /* loop until all desired bytes were send or an error occurred */
1744 sal_uInt32 BytesSend= 0;
1745 sal_uInt32 BytesToSend= n;
1746 sal_uInt8 const *Ptr = static_cast<sal_uInt8 const *>(pBuffer);
1748 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1750 while (BytesToSend > 0)
1752 sal_Int32 RetVal;
1754 RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
1756 /* error occurred? */
1757 if(RetVal <= 0)
1759 break;
1762 BytesToSend -= RetVal;
1763 BytesSend += RetVal;
1764 Ptr += RetVal;
1767 return BytesSend;
1770 static bool socket_poll (
1771 oslSocket pSocket,
1772 const TimeValue* pTimeout,
1773 short nEvent)
1775 struct pollfd fds;
1776 int timeout;
1777 int result;
1779 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1780 if (pSocket == nullptr)
1781 return false; /* EINVAL */
1783 pSocket->m_nLastError = 0;
1785 fds.fd = pSocket->m_Socket;
1786 fds.events = nEvent;
1787 fds.revents = 0;
1789 timeout = -1;
1790 if (pTimeout)
1792 timeout = convertToMs(pTimeout);
1795 result = poll (&fds, 1, timeout);
1796 if (result < 0)
1798 pSocket->m_nLastError = errno;
1799 int nErrno = errno;
1800 SAL_WARN( "sal.osl", "poll failed: " << UnixErrnoString(nErrno) );
1801 return false;
1803 if (result == 0)
1805 /* Timeout */
1806 return false;
1809 return ((fds.revents & nEvent) == nEvent);
1812 sal_Bool SAL_CALL osl_isReceiveReady (
1813 oslSocket pSocket, const TimeValue* pTimeout)
1815 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1816 if (pSocket == nullptr)
1818 /* ENOTSOCK */
1819 return false;
1822 return socket_poll (pSocket, pTimeout, POLLIN);
1825 sal_Bool SAL_CALL osl_isSendReady (
1826 oslSocket pSocket, const TimeValue* pTimeout)
1828 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1829 if (pSocket == nullptr)
1831 /* ENOTSOCK */
1832 return false;
1835 return socket_poll (pSocket, pTimeout, POLLOUT);
1838 sal_Bool SAL_CALL osl_isExceptionPending (
1839 oslSocket pSocket, const TimeValue* pTimeout)
1841 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1842 if (pSocket == nullptr)
1844 /* ENOTSOCK */
1845 return false;
1848 return socket_poll (pSocket, pTimeout, POLLPRI);
1851 sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
1852 oslSocketDirection Direction)
1854 int nRet;
1856 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1857 if ( pSocket == nullptr )
1859 return false;
1862 pSocket->m_nLastError=0;
1864 nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
1865 if (nRet != 0 )
1867 pSocket->m_nLastError=errno;
1868 int nErrno = errno;
1869 SAL_WARN( "sal.osl", "shutdown failed: " << UnixErrnoString(nErrno) );
1871 return (nRet==0);
1874 sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
1875 oslSocketOptionLevel Level,
1876 oslSocketOption Option,
1877 void* pBuffer,
1878 sal_uInt32 BufferLen)
1880 socklen_t nOptLen = static_cast<socklen_t>(BufferLen);
1882 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1883 if ( pSocket == nullptr )
1885 return -1;
1888 pSocket->m_nLastError=0;
1890 if(getsockopt(pSocket->m_Socket,
1891 OPTION_LEVEL_TO_NATIVE(Level),
1892 OPTION_TO_NATIVE(Option),
1893 pBuffer,
1894 &nOptLen) == -1)
1896 pSocket->m_nLastError=errno;
1897 return -1;
1900 return nOptLen;
1903 sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
1904 oslSocketOptionLevel Level,
1905 oslSocketOption Option,
1906 void* pBuffer,
1907 sal_uInt32 BufferLen)
1909 int nRet;
1911 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1912 if ( pSocket == nullptr )
1914 return false;
1917 pSocket->m_nLastError=0;
1919 nRet = setsockopt(pSocket->m_Socket,
1920 OPTION_LEVEL_TO_NATIVE(Level),
1921 OPTION_TO_NATIVE(Option),
1922 pBuffer,
1923 BufferLen);
1925 if ( nRet < 0 )
1927 pSocket->m_nLastError=errno;
1928 return false;
1931 return true;
1934 sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
1935 sal_Bool On)
1937 int flags;
1938 int nRet;
1940 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1941 if ( pSocket == nullptr )
1943 return false;
1946 pSocket->m_nLastError=0;
1948 flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
1950 if (On)
1951 flags |= O_NONBLOCK;
1952 else
1953 flags &= ~(O_NONBLOCK);
1955 nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
1957 if ( nRet < 0 )
1959 pSocket->m_nLastError=errno;
1960 return false;
1963 return true;
1966 sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
1968 int flags;
1970 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1971 if ( pSocket == nullptr )
1973 return false;
1976 pSocket->m_nLastError=0;
1978 flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
1980 if (flags == -1 || !(flags & O_NONBLOCK))
1981 return false;
1983 return true;
1986 oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
1988 int Type=0;
1989 socklen_t TypeSize= sizeof(Type);
1991 SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1992 if ( pSocket == nullptr )
1994 return osl_Socket_TypeInvalid;
1997 pSocket->m_nLastError=0;
1999 if(getsockopt(pSocket->m_Socket,
2000 OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
2001 OPTION_TO_NATIVE(osl_Socket_OptionType),
2002 &Type,
2003 &TypeSize) == -1)
2005 /* error */
2006 pSocket->m_nLastError=errno;
2007 return osl_Socket_TypeInvalid;
2010 return TYPE_FROM_NATIVE(Type);
2014 void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
2016 char pszError[1024];
2018 pszError[0] = '\0';
2020 osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
2022 rtl_uString_newFromAscii(ustrError,pszError);
2025 void osl_psz_getLastSocketErrorDescription(oslSocket pSocket, char* pBuffer, sal_uInt32 BufferSize)
2027 /* make sure pBuffer will be a zero-terminated string even when strncpy has to cut */
2028 pBuffer[BufferSize-1]= '\0';
2030 if ( pSocket == nullptr )
2032 strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
2033 return;
2036 strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
2039 oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
2041 if ( pSocket == nullptr )
2043 return ERROR_FROM_NATIVE(EINVAL);
2046 return ERROR_FROM_NATIVE(pSocket->m_nLastError);
2049 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */