Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / sal / osl / unx / socket.c
blobd11297f6268b2f753e8bd3acb5ff898b95a80abb
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 "system.h"
22 #include <osl/socket.h>
23 #include <osl/diagnose.h>
24 #include <osl/mutex.h>
25 #include <osl/signal.h>
27 #include <rtl/alloc.h>
29 #include <ctype.h>
30 #include <sal/types.h>
32 #include "sockimpl.h"
34 /* defines for poll */
35 #ifdef HAVE_POLL_H
36 #undef HAVE_POLL_H
37 #endif
39 #if defined(LINUX) || defined(NETBSD) || defined ( FREEBSD ) || \
40 defined (MACOSX) || defined (OPENBSD) || defined(DRAGONFLY)
41 #include <sys/poll.h>
42 #define HAVE_POLL_H
43 #endif /* HAVE_POLL_H */
45 #if defined(SOLARIS)
46 #include <poll.h>
47 #define HAVE_POLL_H
48 #endif /* SOLARIS */
50 #ifndef HAVE_POLL_H
51 #define POLLIN 0x0001
52 #define POLLOUT 0x0002
53 #define POLLPRI 0x0004
54 #endif /* HAVE_POLL_H */
56 /* defines for shutdown */
57 #define SD_RECEIVE 0
58 #define SD_SEND 1
59 #define SD_BOTH 2
62 oslSocketAddr is a pointer to a Berkeley struct sockaddr.
63 I refrained from using sockaddr_in because of possible further
64 extensions of this socket-interface (IP-NG?).
65 The intention was to hide all Berkeley data-structures from
66 direct access past the osl-interface.
68 The current implementation is internet (IP) centered. All
69 the constructor-functions (osl_create...) take parameters
70 that will probably make sense only in the IP-environment
71 (e.g. because of using the dotted-address-format).
73 If the interface will be extended to host other protocol-
74 families, I expect no externally visible changes in the
75 existing functions. You'll probably need only new
76 constructor-functions who take the different address
77 formats into consideration (maybe a long dotted address
78 or whatever).
81 /* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */
82 /* are the same! I don't like it very much but see no other easy way to */
83 /* conceal the struct sockaddr from the eyes of the user. */
85 #define OSL_INVALID_SOCKET -1
86 #define OSL_SOCKET_ERROR -1
88 /* Buffer size for gethostbyname */
89 #define MAX_HOSTBUFFER_SIZE 2048
91 /*****************************************************************************/
92 /* enum oslAddrFamily */
93 /*****************************************************************************/
95 /* map */
96 static const unsigned long FamilyMap[]= {
97 AF_INET, /* osl_Socket_FamilyInet */
98 AF_IPX, /* osl_Socket_FamilyIpx */
99 0 /* osl_Socket_FamilyInvalid */
102 /* reverse map */
103 static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
105 oslAddrFamily i= (oslAddrFamily)0;
107 while(i != osl_Socket_FamilyInvalid)
109 if(FamilyMap[i] == nativeType)
110 return i;
111 i = (oslAddrFamily) ( i + 1 );
114 return i;
117 /* macros */
118 #define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
119 #define FAMILY_TO_NATIVE(x) (short)FamilyMap[x]
121 /*****************************************************************************/
122 /* enum oslProtocol */
123 /*****************************************************************************/
125 /* map */
126 static const sal_uInt32 ProtocolMap[]= {
127 0, /* osl_Socket_ProtocolIp */
128 NSPROTO_IPX, /* osl_Socket_ProtocolIpx */
129 NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
130 NSPROTO_SPXII, /* osl_Socket_ProtocolSpxII */
131 0 /* osl_Socket_ProtocolInvalid */
134 /* reverse map */
135 /* mfe: NOT USED
136 static oslProtocol osl_ProtocolFromNative(sal_uInt32 nativeType)
138 oslProtocol i= (oslProtocol)0;
140 while(i != osl_Socket_ProtocolInvalid)
142 if(ProtocolMap[i] == nativeType)
143 return i;
144 i = (oslProtocol) ( i + 1);
147 return i;
151 /* macros */
152 #define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
154 /*****************************************************************************/
155 /* enum oslSocketType */
156 /*****************************************************************************/
158 /* map */
159 static const sal_uInt32 TypeMap[]= {
160 SOCK_STREAM, /* osl_Socket_TypeStream */
161 SOCK_DGRAM, /* osl_Socket_TypeDgram */
162 SOCK_RAW, /* osl_Socket_TypeRaw */
163 SOCK_RDM, /* osl_Socket_TypeRdm */
164 SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */
165 0 /* osl_Socket_TypeInvalid */
168 /* reverse map */
169 static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType)
171 oslSocketType i= (oslSocketType)0;
173 while(i != osl_Socket_TypeInvalid)
175 if(TypeMap[i] == nativeType)
176 return i;
177 i = (oslSocketType)(i + 1);
180 return i;
183 /* macros */
184 #define TYPE_TO_NATIVE(x) TypeMap[x]
185 #define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
187 /*****************************************************************************/
188 /* enum oslSocketOption */
189 /*****************************************************************************/
191 /* map */
192 static const sal_uInt32 OptionMap[]= {
193 SO_DEBUG, /* osl_Socket_OptionDebug */
194 SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */
195 SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */
196 SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */
197 SO_DONTROUTE, /* osl_Socket_OptionDontRoute */
198 SO_BROADCAST, /* osl_Socket_OptionBroadcast */
199 SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */
200 SO_LINGER, /* osl_Socket_OptionLinger */
201 SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */
202 SO_SNDBUF, /* osl_Socket_OptionSndBuf */
203 SO_RCVBUF, /* osl_Socket_OptionRcvBuf */
204 SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */
205 SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */
206 SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */
207 SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */
208 SO_ERROR, /* osl_Socket_OptionError */
209 SO_TYPE, /* osl_Socket_OptionType */
210 TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */
211 0 /* osl_Socket_OptionInvalid */
214 /* reverse map */
215 /* mfe: NOT USED
216 static oslSocketOption osl_SocketOptionFromNative(sal_uInt32 nativeType)
218 oslSocketOption i= (oslSocketOption)0;
220 while(i != osl_Socket_OptionInvalid)
222 if(OptionMap[i] == nativeType)
223 return i;
224 i = (oslSocketOption) ( i + 1 );
227 return i;
230 /* macros */
231 #define OPTION_TO_NATIVE(x) OptionMap[x]
233 /*****************************************************************************/
234 /* enum oslSocketOptionLevel */
235 /*****************************************************************************/
237 static const sal_uInt32 OptionLevelMap[]= {
238 SOL_SOCKET, /* osl_Socket_LevelSocket */
239 IPPROTO_TCP, /* osl_Socket_LevelTcp */
240 0 /* osl_Socket_LevelInvalid */
243 /* reverse map */
244 /* mfe: NOT USED
245 static oslSocketOptionLevel osl_SocketOptionLevelFromNative(sal_uInt32 nativeType)
247 oslSocketOptionLevel i= (oslSocketOptionLevel)0;
249 while(i != osl_Socket_LevelInvalid)
251 if(OptionLevelMap[i] == nativeType)
252 return i;
253 i = (oslSocketOptionLevel) ( i + 1 );
256 return i;
259 /* macros */
260 #define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
262 /*****************************************************************************/
263 /* enum oslSocketMsgFlag */
264 /*****************************************************************************/
266 static const sal_uInt32 SocketMsgFlagMap[]= {
267 0, /* osl_Socket_MsgNormal */
268 MSG_OOB, /* osl_Socket_MsgOOB */
269 MSG_PEEK, /* osl_Socket_MsgPeek */
270 MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */
271 MSG_MAXIOVLEN, /* osl_Socket_MsgMaxIOVLen */
272 0 /* osl_Socket_MsgInvalid */
275 /* reverse map */
276 /* mfe: NOT USED
277 static oslSocketMsgFlag osl_SocketMsgFlagFromNative(sal_uInt32 nativeType)
279 oslSocketMsgFlag i= (oslSocketMsgFlag)0;
281 while(i != osl_Socket_MsgInvalid)
283 if(SocketMsgFlagMap[i] == nativeType)
284 return i;
285 i = (oslSocketMsgFlag) ( i + 1 );
288 return i;
292 /* macros */
293 #define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
295 /*****************************************************************************/
296 /* enum oslSocketDirection */
297 /*****************************************************************************/
299 static const sal_uInt32 SocketDirection[]= {
300 SD_RECEIVE, /* osl_Socket_DirRead */
301 SD_SEND, /* osl_Socket_DirWrite */
302 SD_BOTH, /* osl_Socket_DirReadWrite */
303 0 /* osl_Socket_DirInvalid */
306 /* reverse map */
307 /* mfe: NOT USED
308 static oslSocketDirection osl_SocketDirectionFromNative(sal_uInt32 nativeType)
310 oslSocketDirection i= (oslSocketDirection)0;
312 while(i != osl_Socket_DirInvalid)
314 if(SocketDirection[i] == nativeType)
315 return i;
316 i = (oslSocketDirection) ( i + 1 );
319 return i;
323 /* macros */
324 #define DIRECTION_TO_NATIVE(x) SocketDirection[x]
326 /*****************************************************************************/
327 /* enum oslSocketError */
328 /*****************************************************************************/
330 static const struct
332 int errcode;
333 oslSocketError error;
334 } SocketError[]= {
335 { 0, osl_Socket_E_None }, /* no error */
336 { ENOTSOCK, osl_Socket_E_NotSocket }, /* Socket operation on non-socket */
337 { EDESTADDRREQ, osl_Socket_E_DestAddrReq }, /* Destination address required */
338 { EMSGSIZE, osl_Socket_E_MsgSize }, /* Message too long */
339 { EPROTOTYPE, osl_Socket_E_Prototype }, /* Protocol wrong type for socket */
340 { ENOPROTOOPT, osl_Socket_E_NoProtocol }, /* Protocol not available */
341 { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */
342 { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport }, /* Socket type not supported */
343 { EOPNOTSUPP, osl_Socket_E_OpNotSupport }, /* Operation not supported on socket */
344 { EPFNOSUPPORT, osl_Socket_E_PfNoSupport }, /* Protocol family not supported */
345 { EAFNOSUPPORT, osl_Socket_E_AfNoSupport }, /* Address family not supported by */
346 /* protocol family */
347 { EADDRINUSE, osl_Socket_E_AddrInUse }, /* Address already in use */
348 { EADDRNOTAVAIL, osl_Socket_E_AddrNotAvail }, /* Can't assign requested address */
349 { ENETDOWN, osl_Socket_E_NetDown }, /* Network is down */
350 { ENETUNREACH, osl_Socket_E_NetUnreachable }, /* Network is unreachable */
351 { ENETRESET, osl_Socket_E_NetReset }, /* Network dropped connection because */
352 /* of reset */
353 { ECONNABORTED, osl_Socket_E_ConnAborted }, /* Software caused connection abort */
354 { ECONNRESET, osl_Socket_E_ConnReset }, /* Connection reset by peer */
355 { ENOBUFS, osl_Socket_E_NoBufferSpace }, /* No buffer space available */
356 { EISCONN, osl_Socket_E_IsConnected }, /* Socket is already connected */
357 { ENOTCONN, osl_Socket_E_NotConnected }, /* Socket is not connected */
358 { ESHUTDOWN, osl_Socket_E_Shutdown }, /* Can't send after socket shutdown */
359 { ETOOMANYREFS, osl_Socket_E_TooManyRefs }, /* Too many references: can't splice */
360 { ETIMEDOUT, osl_Socket_E_TimedOut }, /* Connection timed out */
361 { ECONNREFUSED, osl_Socket_E_ConnRefused }, /* Connection refused */
362 { EHOSTDOWN, osl_Socket_E_HostDown }, /* Host is down */
363 { EHOSTUNREACH, osl_Socket_E_HostUnreachable }, /* No route to host */
364 { EWOULDBLOCK, osl_Socket_E_WouldBlock }, /* call would block on non-blocking socket */
365 { EALREADY, osl_Socket_E_Already }, /* operation already in progress */
366 { EINPROGRESS, osl_Socket_E_InProgress }, /* operation now in progress */
367 { EAGAIN, osl_Socket_E_WouldBlock }, /* same as EWOULDBLOCK */
368 { -1, osl_Socket_E_InvalidError }
371 /* map */
372 /* mfe: NOT USED
373 static int osl_NativeFromSocketError(oslSocketError errorCode)
375 int i = 0;
377 while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
378 (SocketError[i].error != errorCode)) i++;
380 return SocketError[i].errcode;
384 /* reverse map */
385 static oslSocketError osl_SocketErrorFromNative(int nativeType)
387 int i = 0;
389 while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
390 (SocketError[i].errcode != nativeType)) i++;
392 return SocketError[i].error;
395 /* macros */
396 #define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
398 /*****************************************************************************/
399 /* local function prototypes */
400 /*****************************************************************************/
402 oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
403 const sal_Char* pszDottedAddr, sal_Int32 Port);
405 oslHostAddr SAL_CALL osl_psz_createHostAddr (
406 const sal_Char *pszHostname, const oslSocketAddr Addr);
408 oslHostAddr SAL_CALL osl_psz_createHostAddrByName (
409 const sal_Char *pszHostname);
411 const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (
412 const oslHostAddr Addr);
414 oslSocketResult SAL_CALL osl_psz_getLocalHostname (
415 sal_Char *pBuffer, sal_uInt32 nBufLen);
417 oslSocketAddr SAL_CALL osl_psz_resolveHostname (
418 const sal_Char* pszHostname);
420 sal_Int32 SAL_CALL osl_psz_getServicePort (
421 const sal_Char* pszServicename, const sal_Char* pszProtocol);
423 oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr (
424 oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
426 oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr (
427 oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
429 void SAL_CALL osl_psz_getLastSocketErrorDescription (
430 oslSocket Socket, sal_Char* pBuffer, sal_uInt32 BufferSize);
432 #if OSL_DEBUG_LEVEL > 1
433 static sal_uInt32 g_nSocketImpl = 0;
434 static sal_uInt32 g_nSocketAddr = 0;
436 /* sorry, must be implemented otherwise */
438 #endif /* OSL_DEBUG_LEVEL */
440 oslSocket __osl_createSocketImpl(int Socket)
442 oslSocket pSocket;
444 pSocket = (oslSocket)calloc(1, sizeof(struct oslSocketImpl));
446 pSocket->m_Socket = Socket;
447 pSocket->m_nLastError = 0;
448 pSocket->m_nRefCount = 1;
450 #if defined(LINUX)
451 pSocket->m_bIsAccepting = sal_False;
452 #endif
454 #if OSL_DEBUG_LEVEL > 1
455 g_nSocketImpl ++;
456 #endif
457 return pSocket;
460 void __osl_destroySocketImpl(oslSocket Socket)
462 if ( Socket != NULL)
463 free((struct oslSocketImpl *) Socket);
464 #if OSL_DEBUG_LEVEL > 1
465 g_nSocketImpl --;
466 #endif
469 static oslSocketAddr __osl_createSocketAddr( )
471 oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
472 #if OSL_DEBUG_LEVEL > 1
473 g_nSocketAddr ++;
474 #endif
475 return pAddr;
478 static oslSocketAddr __osl_createSocketAddrWithFamily(
479 oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
481 oslSocketAddr pAddr;
483 OSL_ASSERT( family == osl_Socket_FamilyInet );
485 pAddr = __osl_createSocketAddr();
486 switch( family )
488 case osl_Socket_FamilyInet:
490 struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
492 pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
493 pInetAddr->sin_addr.s_addr = nAddr;
494 pInetAddr->sin_port = (sal_uInt16)(port&0xffff);
495 break;
497 default:
498 pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
500 return pAddr;
503 static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
505 oslSocketAddr pAddr = __osl_createSocketAddr();
506 memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) );
507 return pAddr;
510 static void __osl_destroySocketAddr( oslSocketAddr addr )
512 #if OSL_DEBUG_LEVEL > 1
513 g_nSocketAddr --;
514 #endif
515 rtl_freeMemory( addr );
518 oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
520 oslSocketAddr pAddr = 0;
522 /* is it an internet-Addr? */
523 if (Family == osl_Socket_FamilyInet)
525 pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
527 else
529 pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 );
532 return pAddr;
535 oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
537 oslSocketAddr pCopy = 0;
538 if (Addr)
540 pCopy = __osl_createSocketAddr();
542 if (pCopy)
543 memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
545 return pCopy;
548 sal_Bool SAL_CALL osl_isEqualSocketAddr (
549 oslSocketAddr Addr1,
550 oslSocketAddr Addr2)
552 struct sockaddr* pAddr1 = NULL;
553 struct sockaddr* pAddr2 = NULL;
555 OSL_ASSERT(Addr1);
556 OSL_ASSERT(Addr2);
557 pAddr1 = &(Addr1->m_sockaddr);
558 pAddr2 = &(Addr2->m_sockaddr);
560 if (pAddr1 == pAddr2)
562 return (sal_True);
565 if (pAddr1->sa_family == pAddr2->sa_family)
567 switch (pAddr1->sa_family)
569 case AF_INET:
571 struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1;
572 struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2;
574 if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
575 (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
576 (pInetAddr1->sin_port == pInetAddr2->sin_port))
577 return (sal_True);
580 default:
582 return (memcmp(pAddr1, pAddr2, sizeof(struct sockaddr)) == 0);
587 return (sal_False);
590 oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
591 rtl_uString *strDottedAddr,
592 sal_Int32 Port)
594 sal_uInt32 nAddr = OSL_INADDR_NONE;
595 oslSocketAddr pAddr;
597 if (strDottedAddr && strDottedAddr->length)
599 /* Dotted host address for limited broadcast */
600 rtl_String *pDottedAddr = NULL;
602 rtl_uString2String (
603 &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
604 RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
606 nAddr = inet_addr (pDottedAddr->buffer);
607 rtl_string_release (pDottedAddr);
610 if (nAddr != OSL_INADDR_NONE)
612 /* Limited broadcast */
613 nAddr = ntohl(nAddr);
614 if (IN_CLASSA(nAddr))
616 nAddr &= IN_CLASSA_NET;
617 nAddr |= IN_CLASSA_HOST;
619 else if (IN_CLASSB(nAddr))
621 nAddr &= IN_CLASSB_NET;
622 nAddr |= IN_CLASSB_HOST;
624 else if (IN_CLASSC(nAddr))
626 nAddr &= IN_CLASSC_NET;
627 nAddr |= IN_CLASSC_HOST;
629 else
631 /* No broadcast in class D */
632 return ((oslSocketAddr)NULL);
634 nAddr = htonl(nAddr);
637 pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
638 return pAddr;
641 oslSocketAddr SAL_CALL osl_createInetSocketAddr (
642 rtl_uString *ustrDottedAddr,
643 sal_Int32 Port)
645 rtl_String* strDottedAddr=0;
646 oslSocketAddr Addr;
647 sal_Char* pszDottedAddr=0;
649 if ( ustrDottedAddr != 0 )
651 rtl_uString2String( &strDottedAddr,
652 rtl_uString_getStr(ustrDottedAddr),
653 rtl_uString_getLength(ustrDottedAddr),
654 RTL_TEXTENCODING_UTF8,
655 OUSTRING_TO_OSTRING_CVTFLAGS);
656 pszDottedAddr = rtl_string_getStr(strDottedAddr);
659 Addr = osl_psz_createInetSocketAddr(pszDottedAddr, Port);
661 if ( strDottedAddr != 0 )
663 rtl_string_release(strDottedAddr);
666 return Addr;
669 oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
670 const sal_Char* pszDottedAddr,
671 sal_Int32 Port)
673 oslSocketAddr pAddr = 0;
674 sal_Int32 Addr = inet_addr(pszDottedAddr);
675 if(Addr != -1)
677 /* valid dotted addr */
678 pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , Addr );
680 return pAddr;
683 oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
685 oslSocketResult res = osl_Socket_Error;
687 OSL_ASSERT( pAddr );
688 OSL_ASSERT( pByteSeq );
690 if( pAddr && pByteSeq )
692 struct sockaddr_in * pSystemInetAddr;
694 OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
695 OSL_ASSERT( pByteSeq->nElements == 4 );
697 pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
698 memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
699 res = osl_Socket_Ok;
701 return res;
704 oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
706 oslSocketResult res = osl_Socket_Error;
708 OSL_ASSERT( pAddr );
709 OSL_ASSERT( ppByteSeq );
711 if( pAddr && ppByteSeq )
713 struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
714 rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4);
715 res = osl_Socket_Ok;
717 return res;
720 /** try to figure out a full-qualified hostname, by adding the current domain
721 as given by the domainname program to the given hostname.
722 This function MUST NOT call gethostbyname since pHostName already points
723 to data returned by gethostname and would be garbled: use gethostname_r
724 instead!
727 /* wrap around different interfaces to reentrant gethostbyname */
728 static struct hostent* _osl_gethostbyname_r (
729 const char *name, struct hostent *result,
730 char *buffer, int buflen, int *h_errnop)
732 #if defined(LINUX) || defined(ANDROID) || (defined(FREEBSD) && (__FreeBSD_version >= 601103)) || defined(DRAGONFLY)
733 struct hostent *__result; /* will be the same as result */
734 int __error;
735 __error = gethostbyname_r (name, result, buffer, buflen,
736 &__result, h_errnop);
737 return __error ? NULL : __result ;
738 #elif defined(AIX)
739 *h_errnop = gethostbyname_r (name, result, (struct hostent_data *)buffer);
740 (void)buflen;
741 return *h_errnop ? NULL : result ;
742 #else
743 return gethostbyname_r( name, result, buffer, buflen, h_errnop);
744 #endif
747 static sal_Char* _osl_getFullQualifiedDomainName (const sal_Char *pHostName)
749 struct hostent aHostByName;
750 struct hostent *pHostByName;
751 sal_Char pQualifiedHostBuffer[ MAX_HOSTBUFFER_SIZE ];
752 sal_Char *pFullQualifiedName = NULL;
753 int nErrorNo;
755 pHostByName = _osl_gethostbyname_r (
756 pHostName,
757 &aHostByName, pQualifiedHostBuffer,
758 sizeof(pQualifiedHostBuffer), &nErrorNo );
759 if (pHostByName != NULL)
761 pFullQualifiedName = strdup(pHostByName->h_name);
763 return pFullQualifiedName;
766 static sal_Bool _osl_isFullQualifiedDomainName (const sal_Char *pHostName)
768 /* a FQDN (aka 'hostname.domain.top_level_domain' )
769 * is a name which contains a dot '.' in it ( would
770 * match as well for 'hostname.' but is good enough
771 * for now )*/
772 return (sal_Bool)( strchr( pHostName, (int)'.' ) != NULL );
775 struct oslHostAddrImpl
777 sal_Char *pHostName;
778 oslSocketAddr pSockAddr;
781 static oslHostAddr _osl_hostentToHostAddr (const struct hostent *he)
783 oslHostAddr pAddr= NULL;
784 oslSocketAddr pSockAddr = 0;
786 sal_Char *cn;
788 if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
789 return ((oslHostAddr)NULL);
791 if (_osl_isFullQualifiedDomainName(he->h_name))
793 cn= strdup(he->h_name);
794 OSL_ASSERT(cn);
795 if (cn == NULL)
796 return ((oslHostAddr)NULL);
798 else
800 cn =_osl_getFullQualifiedDomainName (he->h_name);
801 OSL_ASSERT(cn);
802 if (cn == NULL)
803 return ((oslHostAddr)NULL);
806 pSockAddr = __osl_createSocketAddr();
807 OSL_ASSERT(pSockAddr);
808 if (pSockAddr == NULL)
810 free(cn);
811 return ((oslHostAddr)NULL);
814 pSockAddr->m_sockaddr.sa_family= he->h_addrtype;
815 if (pSockAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
817 struct sockaddr_in *sin= (struct sockaddr_in *)&(pSockAddr->m_sockaddr);
818 memcpy (
819 &(sin->sin_addr.s_addr),
820 he->h_addr_list[0],
821 he->h_length);
823 else
825 /* unknown address family */
826 /* future extensions for new families might be implemented here */
828 OSL_TRACE("_osl_hostentToHostAddr: unknown address family.");
829 OSL_ASSERT(sal_False);
831 __osl_destroySocketAddr( pSockAddr );
832 free (cn);
833 return ((oslHostAddr)NULL);
836 pAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
837 OSL_ASSERT(pAddr);
838 if (pAddr == NULL)
840 __osl_destroySocketAddr( pSockAddr );
841 free (cn);
842 return ((oslHostAddr)NULL);
845 pAddr->pHostName= cn;
846 pAddr->pSockAddr= pSockAddr;
848 return pAddr;
851 oslHostAddr SAL_CALL osl_createHostAddr (
852 rtl_uString *ustrHostname,
853 const oslSocketAddr Addr)
855 oslHostAddr HostAddr;
856 rtl_String* strHostname=0;
857 sal_Char* pszHostName=0;
859 if ( ustrHostname != 0 )
861 rtl_uString2String( &strHostname,
862 rtl_uString_getStr(ustrHostname),
863 rtl_uString_getLength(ustrHostname),
864 RTL_TEXTENCODING_UTF8,
865 OUSTRING_TO_OSTRING_CVTFLAGS );
866 pszHostName = rtl_string_getStr(strHostname);
869 HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
871 if ( strHostname != 0 )
873 rtl_string_release(strHostname);
876 return HostAddr;
879 oslHostAddr SAL_CALL osl_psz_createHostAddr (
880 const sal_Char *pszHostname,
881 const oslSocketAddr pAddr)
883 oslHostAddr pHostAddr;
884 sal_Char *cn;
886 OSL_ASSERT(pszHostname && pAddr);
887 if ((pszHostname == NULL) || (pAddr == NULL))
888 return ((oslHostAddr)NULL);
890 cn = strdup(pszHostname);
891 OSL_ASSERT(cn);
892 if (cn == NULL)
893 return ((oslHostAddr)NULL);
895 pHostAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
896 OSL_ASSERT(pHostAddr);
897 if (pHostAddr == NULL)
899 free (cn);
900 return ((oslHostAddr)NULL);
903 pHostAddr->pHostName= cn;
904 pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
906 return pHostAddr;
909 oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
911 oslHostAddr HostAddr;
912 rtl_String* strHostname=0;
913 sal_Char* pszHostName=0;
915 if ( ustrHostname != 0 )
917 rtl_uString2String( &strHostname,
918 rtl_uString_getStr(ustrHostname),
919 rtl_uString_getLength(ustrHostname),
920 RTL_TEXTENCODING_UTF8,
921 OUSTRING_TO_OSTRING_CVTFLAGS );
922 pszHostName=rtl_string_getStr(strHostname);
925 HostAddr = osl_psz_createHostAddrByName(pszHostName);
927 if ( strHostname != 0 )
929 rtl_string_release(strHostname);
932 return HostAddr;
935 oslHostAddr SAL_CALL osl_psz_createHostAddrByName (const sal_Char *pszHostname)
937 struct hostent aHe;
938 struct hostent *pHe;
939 sal_Char heBuffer[ MAX_HOSTBUFFER_SIZE ];
940 int nErrorNo;
942 pHe = _osl_gethostbyname_r (
943 pszHostname,
944 &aHe, heBuffer,
945 sizeof(heBuffer), &nErrorNo );
947 return _osl_hostentToHostAddr (pHe);
950 oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
952 OSL_ASSERT(pAddr);
954 if (pAddr == NULL)
955 return ((oslHostAddr)NULL);
957 if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
959 const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr);
960 struct hostent *he;
962 if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
963 return ((oslHostAddr)NULL);
965 he= gethostbyaddr((sal_Char *)&(sin->sin_addr),
966 sizeof (sin->sin_addr),
967 sin->sin_family);
968 return _osl_hostentToHostAddr (he);
971 return ((oslHostAddr)NULL);
974 oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr)
976 OSL_ASSERT(pAddr);
978 if (pAddr)
979 return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
980 else
981 return ((oslHostAddr)NULL);
984 void SAL_CALL osl_getHostnameOfHostAddr (
985 const oslHostAddr Addr,
986 rtl_uString **ustrHostname)
988 const sal_Char* pHostname=0;
990 pHostname = osl_psz_getHostnameOfHostAddr(Addr);
992 rtl_uString_newFromAscii (ustrHostname, pHostname);
994 return;
997 const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
999 if (pAddr)
1000 return pAddr->pHostName;
1001 else
1002 return NULL;
1005 oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
1007 OSL_ASSERT(pAddr);
1009 if (pAddr)
1010 return ((oslSocketAddr)(pAddr->pSockAddr));
1011 else
1012 return NULL;
1015 void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
1017 if (pAddr)
1019 if (pAddr->pHostName)
1020 free (pAddr->pHostName);
1021 if (pAddr->pSockAddr)
1022 osl_destroySocketAddr (pAddr->pSockAddr);
1023 free (pAddr);
1027 oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
1029 oslSocketResult Result;
1030 sal_Char pszHostname[1024];
1032 pszHostname[0] = '\0';
1034 Result = osl_psz_getLocalHostname(pszHostname,sizeof(pszHostname));
1036 rtl_uString_newFromAscii(ustrLocalHostname,pszHostname);
1038 return Result;
1041 oslSocketResult SAL_CALL osl_psz_getLocalHostname (
1042 sal_Char *pBuffer, sal_uInt32 nBufLen)
1044 static sal_Char LocalHostname[256] = "";
1046 if (strlen(LocalHostname) == 0)
1048 const sal_Char *pStr;
1050 #ifdef SYSV
1051 struct utsname uts;
1053 if (uname(&uts) < 0)
1054 return osl_Socket_Error;
1056 if ((strlen(uts.nodename) + 1) > nBufLen)
1057 return osl_Socket_Error;
1059 strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
1060 #else /* BSD compatible */
1062 if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
1063 return osl_Socket_Error;
1064 LocalHostname[sizeof(LocalHostname)-1] = 0;
1065 #endif /* SYSV */
1067 /* check if we have an FQDN */
1068 if (strchr(LocalHostname, '.') == NULL)
1070 oslHostAddr Addr;
1072 /* no, determine it via dns */
1073 Addr = osl_psz_createHostAddrByName(LocalHostname);
1075 if ((pStr = osl_psz_getHostnameOfHostAddr(Addr)) != NULL)
1077 strcpy(LocalHostname, pStr);
1079 osl_destroyHostAddr(Addr);
1083 if (strlen(LocalHostname) > 0)
1085 strncpy(pBuffer, LocalHostname, nBufLen);
1086 pBuffer[nBufLen - 1] = '\0';
1088 return osl_Socket_Ok;
1091 return osl_Socket_Error;
1094 oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
1096 oslSocketAddr Addr;
1097 rtl_String* strHostname=0;
1098 sal_Char* pszHostName=0;
1100 if ( ustrHostname != 0 )
1102 rtl_uString2String( &strHostname,
1103 rtl_uString_getStr(ustrHostname),
1104 rtl_uString_getLength(ustrHostname),
1105 RTL_TEXTENCODING_UTF8,
1106 OUSTRING_TO_OSTRING_CVTFLAGS );
1107 pszHostName = rtl_string_getStr(strHostname);
1110 Addr = osl_psz_resolveHostname(pszHostName);
1112 if ( strHostname != 0 )
1114 rtl_string_release(strHostname);
1117 return Addr;
1120 oslSocketAddr SAL_CALL osl_psz_resolveHostname(const sal_Char* pszHostname)
1122 struct oslHostAddrImpl *pAddr = (oslHostAddr)osl_psz_createHostAddrByName(pszHostname);
1124 if (pAddr)
1126 oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr);
1128 osl_destroyHostAddr(pAddr);
1130 return (SockAddr);
1133 return ((oslSocketAddr)NULL);
1136 sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol)
1138 sal_Int32 nPort;
1139 rtl_String* strServicename=0;
1140 rtl_String* strProtocol=0;
1141 sal_Char* pszServiceName=0;
1142 sal_Char* pszProtocol=0;
1144 if ( ustrServicename != 0 )
1146 rtl_uString2String( &strServicename,
1147 rtl_uString_getStr(ustrServicename),
1148 rtl_uString_getLength(ustrServicename),
1149 RTL_TEXTENCODING_UTF8,
1150 OUSTRING_TO_OSTRING_CVTFLAGS );
1151 pszServiceName = rtl_string_getStr(strServicename);
1154 if ( ustrProtocol != 0 )
1156 rtl_uString2String( &strProtocol,
1157 rtl_uString_getStr(ustrProtocol),
1158 rtl_uString_getLength(ustrProtocol),
1159 RTL_TEXTENCODING_UTF8,
1160 OUSTRING_TO_OSTRING_CVTFLAGS );
1161 pszProtocol = rtl_string_getStr(strProtocol);
1164 nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
1166 if ( strServicename != 0 )
1168 rtl_string_release(strServicename);
1171 if ( strProtocol != 0 )
1173 rtl_string_release(strProtocol);
1176 return nPort;
1179 sal_Int32 SAL_CALL osl_psz_getServicePort(const sal_Char* pszServicename,
1180 const sal_Char* pszProtocol)
1182 struct servent* ps;
1184 ps= getservbyname(pszServicename, pszProtocol);
1186 if (ps != 0)
1187 return ntohs(ps->s_port);
1189 return OSL_INVALID_PORT;
1192 void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
1194 __osl_destroySocketAddr( pAddr );
1197 oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
1199 OSL_ASSERT(pAddr);
1201 if (pAddr)
1202 return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
1203 else
1204 return osl_Socket_FamilyInvalid;
1207 sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
1209 OSL_ASSERT(pAddr);
1210 if( pAddr )
1212 struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
1214 if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1215 return ntohs(pSystemInetAddr->sin_port);
1217 return OSL_INVALID_PORT;
1220 sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port)
1222 OSL_ASSERT(pAddr);
1223 if( pAddr )
1225 struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
1226 if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1228 pSystemInetAddr->sin_port= htons((short)Port);
1229 return sal_True;
1233 /* this is not a inet-addr => can't set port */
1234 return sal_False;
1237 oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
1239 oslSocketResult Result;
1240 sal_Char pszHostname[1024];
1242 pszHostname[0] = '\0';
1244 Result = osl_psz_getHostnameOfSocketAddr(Addr,pszHostname,sizeof(pszHostname));
1246 rtl_uString_newFromAscii(ustrHostname,pszHostname);
1248 return Result;
1251 oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr,
1252 sal_Char *pBuffer, sal_uInt32 BufferSize)
1254 oslHostAddr pHostAddr= (oslHostAddr )osl_createHostAddrByAddr(pAddr);
1256 if (pHostAddr)
1258 strncpy(pBuffer, pHostAddr->pHostName, BufferSize);
1260 pBuffer[BufferSize - 1] = '\0';
1262 osl_destroyHostAddr(pHostAddr);
1264 return osl_Socket_Ok;
1267 return osl_Socket_Error;
1270 /*****************************************************************************/
1271 /* osl_getDottedInetAddrOfSocketAddr */
1272 /*****************************************************************************/
1273 oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
1275 oslSocketResult Result;
1276 sal_Char pszDottedInetAddr[1024];
1278 pszDottedInetAddr[0] = '\0';
1280 Result = osl_psz_getDottedInetAddrOfSocketAddr(Addr,pszDottedInetAddr,sizeof(pszDottedInetAddr));
1282 rtl_uString_newFromAscii(ustrDottedInetAddr,pszDottedInetAddr);
1284 return Result;
1288 oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr,
1289 sal_Char *pBuffer, sal_uInt32 BufferSize)
1291 OSL_ASSERT(pAddr);
1293 if( pAddr )
1295 struct sockaddr_in* pSystemInetAddr = ( struct sockaddr_in * ) &(pAddr->m_sockaddr);
1297 if (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1299 strncpy(pBuffer, inet_ntoa(pSystemInetAddr->sin_addr), BufferSize);
1300 pBuffer[BufferSize - 1] = '\0';
1302 return osl_Socket_Ok;
1306 return osl_Socket_Error;
1309 oslSocket SAL_CALL osl_createSocket(oslAddrFamily Family,
1310 oslSocketType Type,
1311 oslProtocol Protocol)
1313 int Flags;
1314 oslSocket pSocket;
1316 /* alloc memory */
1317 pSocket= __osl_createSocketImpl(OSL_INVALID_SOCKET);
1319 /* create socket */
1320 pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
1321 TYPE_TO_NATIVE(Type),
1322 PROTOCOL_TO_NATIVE(Protocol));
1324 /* creation failed => free memory */
1325 if(pSocket->m_Socket == OSL_INVALID_SOCKET)
1327 OSL_TRACE("osl_createSocket failed. Errno: %d; %s\n",
1328 errno,
1329 strerror(errno));
1331 __osl_destroySocketImpl((pSocket));
1332 pSocket= 0;
1334 else
1336 /* set close-on-exec flag */
1337 if ((Flags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
1339 Flags |= FD_CLOEXEC;
1340 if (fcntl(pSocket->m_Socket, F_SETFD, Flags) == -1)
1342 pSocket->m_nLastError=errno;
1343 OSL_TRACE("osl_createSocket failed changing socket flags. Errno: %d; %s\n",
1344 errno,
1345 strerror(errno));
1348 else
1350 pSocket->m_nLastError=errno;
1354 return pSocket;
1357 void SAL_CALL osl_acquireSocket(oslSocket pSocket)
1359 osl_atomic_increment( &(pSocket->m_nRefCount ) );
1362 void SAL_CALL osl_releaseSocket( oslSocket pSocket )
1364 if( pSocket && 0 == osl_atomic_decrement( &(pSocket->m_nRefCount) ) )
1366 #if defined(LINUX)
1367 if ( pSocket->m_bIsAccepting == sal_True )
1369 OSL_FAIL("osl_destroySocket : attempt to destroy socket while accepting\n");
1370 return;
1372 #endif /* LINUX */
1373 osl_closeSocket( pSocket );
1374 __osl_destroySocketImpl( pSocket );
1378 void SAL_CALL osl_closeSocket(oslSocket pSocket)
1380 int nRet;
1381 int nFD;
1383 /* socket already invalid */
1384 if(pSocket==0)
1385 return;
1387 pSocket->m_nLastError=0;
1388 nFD = pSocket->m_Socket;
1390 if (nFD == OSL_INVALID_SOCKET)
1391 return;
1393 pSocket->m_Socket = OSL_INVALID_SOCKET;
1395 #if defined(LINUX)
1396 pSocket->m_bIsInShutdown = sal_True;
1398 if ( pSocket->m_bIsAccepting == sal_True )
1400 int nConnFD;
1401 union {
1402 struct sockaddr aSockAddr;
1403 struct sockaddr_in aSockAddrIn;
1404 } s;
1405 socklen_t nSockLen = sizeof(s.aSockAddr);
1407 nRet = getsockname(nFD, &s.aSockAddr, &nSockLen);
1408 if ( nRet < 0 )
1410 OSL_TRACE("getsockname call failed with error: %s", strerror(errno));
1413 if ( s.aSockAddr.sa_family == AF_INET )
1415 if ( s.aSockAddrIn.sin_addr.s_addr == htonl(INADDR_ANY) )
1417 s.aSockAddrIn.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1420 nConnFD = socket(AF_INET, SOCK_STREAM, 0);
1421 if ( nConnFD < 0 )
1423 OSL_TRACE("socket call failed with error: %s", strerror(errno));
1425 else
1427 nRet = connect(nConnFD, &s.aSockAddr, sizeof(s.aSockAddr));
1428 if ( nRet < 0 )
1430 OSL_TRACE("connect call failed with error: %s", strerror(errno));
1432 close(nConnFD);
1435 pSocket->m_bIsAccepting = sal_False;
1437 #endif /* LINUX */
1439 nRet=close(nFD);
1440 if ( nRet != 0 )
1442 pSocket->m_nLastError=errno;
1443 OSL_TRACE("closeSocket close error '%s'",strerror(errno));
1446 pSocket->m_Socket = OSL_INVALID_SOCKET;
1449 /*****************************************************************************/
1450 /* osl_getLocalAddrOfSocket */
1451 /* Note that I rely on the fact that oslSocketAddr and struct sockaddr */
1452 /* are the same! I don't like it very much but see no other easy way to conceal */
1453 /* the struct sockaddr from the eyes of the user. */
1454 /*****************************************************************************/
1455 oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
1457 socklen_t AddrLen;
1458 struct sockaddr Addr;
1459 oslSocketAddr pAddr;
1461 if (pSocket == NULL) /* ENOTSOCK */
1462 return ((oslSocketAddr)NULL);
1464 AddrLen= sizeof(struct sockaddr);
1466 if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1467 return ((oslSocketAddr)NULL);
1469 pAddr = __osl_createSocketAddrFromSystem( &Addr );
1470 return pAddr;
1473 oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
1475 socklen_t AddrLen;
1476 struct sockaddr Addr;
1478 OSL_ASSERT(pSocket);
1479 if ( pSocket == 0 )
1481 return 0;
1484 pSocket->m_nLastError=0;
1485 AddrLen= sizeof(struct sockaddr);
1487 if(getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1489 pSocket->m_nLastError=errno;
1490 return 0;
1492 return __osl_createSocketAddrFromSystem( &Addr );
1495 sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
1496 oslSocketAddr pAddr)
1498 int nRet;
1500 OSL_ASSERT(pSocket && pAddr );
1501 if ( pSocket == 0 || pAddr == 0 )
1503 return sal_False;
1506 pSocket->m_nLastError=0;
1508 nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
1510 if ( nRet == OSL_SOCKET_ERROR)
1512 pSocket->m_nLastError=errno;
1513 return sal_False;
1516 return sal_True;
1519 sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
1520 sal_Int32 MaxPendingConnections)
1522 int nRet;
1524 OSL_ASSERT(pSocket);
1525 if ( pSocket == 0 )
1527 return sal_False;
1530 pSocket->m_nLastError=0;
1532 nRet = listen(pSocket->m_Socket,
1533 MaxPendingConnections == -1 ?
1534 SOMAXCONN :
1535 MaxPendingConnections);
1536 if ( nRet == OSL_SOCKET_ERROR)
1538 pSocket->m_nLastError=errno;
1539 return sal_False;
1542 return sal_True;
1545 oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
1546 oslSocketAddr pAddr,
1547 const TimeValue* pTimeout)
1549 fd_set WriteSet;
1550 fd_set ExcptSet;
1551 int ReadyHandles;
1552 struct timeval tv;
1553 oslSocketResult Result= osl_Socket_Ok;
1555 OSL_PRECOND(pSocket, "osl_connectSocketTo(): need a valid socket!\n");
1557 if ( pSocket == 0 )
1559 return osl_Socket_Error;
1562 pSocket->m_nLastError=0;
1564 if (osl_isNonBlockingMode(pSocket))
1566 if (connect(pSocket->m_Socket,
1567 &(pAddr->m_sockaddr),
1568 sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1569 return osl_Socket_Ok;
1570 else
1571 if (errno == EWOULDBLOCK || errno == EINPROGRESS)
1573 pSocket->m_nLastError=EINPROGRESS;
1574 return osl_Socket_InProgress;
1577 pSocket->m_nLastError=errno;
1578 OSL_TRACE("can't connect : '%s'",strerror(errno));
1579 return osl_Socket_Error;
1582 /* set socket temporarily to non-blocking */
1583 OSL_VERIFY(osl_enableNonBlockingMode(pSocket, sal_True));
1585 /* initiate connect */
1586 if(connect(pSocket->m_Socket,
1587 &(pAddr->m_sockaddr),
1588 sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1590 /* immediate connection */
1591 osl_enableNonBlockingMode(pSocket, sal_False);
1593 return osl_Socket_Ok;
1595 else
1597 /* really an error or just delayed? */
1598 if (errno != EINPROGRESS)
1600 pSocket->m_nLastError=errno;
1601 OSL_TRACE(
1602 "osl_connectSocketTo(): connect failed: errno: %d (%s)\n",
1603 errno, strerror(errno));
1605 osl_enableNonBlockingMode(pSocket, sal_False);
1606 return osl_Socket_Error;
1610 /* prepare select set for socket */
1611 FD_ZERO(&WriteSet);
1612 FD_ZERO(&ExcptSet);
1613 FD_SET(pSocket->m_Socket, &WriteSet);
1614 FD_SET(pSocket->m_Socket, &ExcptSet);
1616 /* prepare timeout */
1617 if (pTimeout)
1619 /* divide milliseconds into seconds and microseconds */
1620 tv.tv_sec= pTimeout->Seconds;
1621 tv.tv_usec= pTimeout->Nanosec / 1000L;
1624 /* select */
1625 ReadyHandles= select(pSocket->m_Socket+1,
1627 PTR_FD_SET(WriteSet),
1628 PTR_FD_SET(ExcptSet),
1629 (pTimeout) ? &tv : 0);
1631 if (ReadyHandles > 0) /* connected */
1633 if ( FD_ISSET(pSocket->m_Socket, &WriteSet ) )
1635 int nErrorCode = 0;
1636 socklen_t nErrorSize = sizeof( nErrorCode );
1638 int nSockOpt;
1640 nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
1641 &nErrorCode, &nErrorSize );
1642 if ( (nSockOpt == 0) && (nErrorCode == 0))
1643 Result = osl_Socket_Ok;
1644 else
1645 Result = osl_Socket_Error;
1647 else
1649 Result= osl_Socket_Error;
1652 else if (ReadyHandles < 0) /* error */
1654 if (errno == EBADF) /* most probably interrupted by close() */
1656 /* do not access pSockImpl because it is about to be or */
1657 /* already destroyed */
1658 return osl_Socket_Interrupted;
1660 else
1662 pSocket->m_nLastError=errno;
1663 Result= osl_Socket_Error;
1666 else /* timeout */
1668 pSocket->m_nLastError=errno;
1669 Result= osl_Socket_TimedOut;
1672 osl_enableNonBlockingMode(pSocket, sal_False);
1674 return Result;
1677 oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
1678 oslSocketAddr* ppAddr)
1680 struct sockaddr Addr;
1681 int Connection, Flags;
1682 oslSocket pConnectionSockImpl;
1684 socklen_t AddrLen = sizeof(struct sockaddr);
1685 OSL_ASSERT(pSocket);
1686 if ( pSocket == 0 )
1688 return 0;
1691 pSocket->m_nLastError=0;
1692 #if defined(LINUX)
1693 pSocket->m_bIsAccepting = sal_True;
1694 #endif /* LINUX */
1696 if( ppAddr && *ppAddr )
1698 osl_destroySocketAddr( *ppAddr );
1699 *ppAddr = 0;
1702 /* prevent Linux EINTR behaviour */
1705 Connection = accept(pSocket->m_Socket, &Addr, &AddrLen);
1706 } while (Connection == -1 && errno == EINTR);
1708 /* accept failed? */
1709 if( Connection == OSL_SOCKET_ERROR )
1711 pSocket->m_nLastError=errno;
1712 OSL_TRACE("osl_acceptConnectionOnSocket : accept error '%s'",strerror(errno));
1714 #if defined(LINUX)
1715 pSocket->m_bIsAccepting = sal_False;
1716 #endif /* LINUX */
1717 return 0;
1720 OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
1722 #if defined(LINUX)
1723 if ( pSocket->m_bIsInShutdown == sal_True )
1725 close(Connection);
1726 OSL_TRACE("osl_acceptConnectionOnSocket : close while accept");
1727 return 0;
1729 #endif /* LINUX */
1731 if(ppAddr)
1733 *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
1736 /* alloc memory */
1737 pConnectionSockImpl= __osl_createSocketImpl(OSL_INVALID_SOCKET);
1739 /* set close-on-exec flag */
1740 if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
1742 Flags |= FD_CLOEXEC;
1743 if (fcntl(Connection, F_SETFD, Flags) == -1)
1745 pSocket->m_nLastError=errno;
1746 OSL_TRACE("osl_acceptConnectionOnSocket failed changing socket flags. Errno: %d (%s)\n",
1747 errno,
1748 strerror(errno));
1753 pConnectionSockImpl->m_Socket = Connection;
1754 pConnectionSockImpl->m_nLastError = 0;
1755 #if defined(LINUX)
1756 pConnectionSockImpl->m_bIsAccepting = sal_False;
1758 pSocket->m_bIsAccepting = sal_False;
1759 #endif /* LINUX */
1760 return pConnectionSockImpl;
1763 sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
1764 void* pBuffer,
1765 sal_uInt32 BytesToRead,
1766 oslSocketMsgFlag Flag)
1768 int nRead;
1770 OSL_ASSERT(pSocket);
1771 if ( pSocket == 0 )
1773 OSL_TRACE("osl_receiveSocket : Invalid socket");
1774 return -1;
1777 pSocket->m_nLastError=0;
1781 nRead = recv(pSocket->m_Socket,
1782 (sal_Char*)pBuffer,
1783 BytesToRead,
1784 MSG_FLAG_TO_NATIVE(Flag));
1785 } while ( nRead < 0 && errno == EINTR );
1787 if ( nRead < 0 )
1789 pSocket->m_nLastError=errno;
1790 OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,strerror(errno));
1792 else if ( nRead == 0 )
1794 OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
1797 return nRead;
1800 sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
1801 oslSocketAddr pSenderAddr,
1802 void* pBuffer,
1803 sal_uInt32 BufferSize,
1804 oslSocketMsgFlag Flag)
1806 int nRead;
1807 struct sockaddr *pSystemSockAddr = 0;
1808 socklen_t AddrLen = 0;
1809 if( pSenderAddr )
1811 AddrLen = sizeof( struct sockaddr );
1812 pSystemSockAddr = &(pSenderAddr->m_sockaddr);
1815 OSL_ASSERT(pSocket);
1816 if ( pSocket == 0 )
1818 OSL_TRACE("osl_receiveFromSocket : Invalid socket");
1819 return -1;
1822 pSocket->m_nLastError=0;
1824 nRead = recvfrom(pSocket->m_Socket,
1825 (sal_Char*)pBuffer,
1826 BufferSize,
1827 MSG_FLAG_TO_NATIVE(Flag),
1828 pSystemSockAddr,
1829 &AddrLen);
1831 if ( nRead < 0 )
1833 pSocket->m_nLastError=errno;
1834 OSL_TRACE("osl_receiveFromSocket failed : %i '%s'",nRead,strerror(errno));
1836 else if ( nRead == 0 )
1838 OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
1841 return nRead;
1844 sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
1845 const void* pBuffer,
1846 sal_uInt32 BytesToSend,
1847 oslSocketMsgFlag Flag)
1849 int nWritten;
1851 OSL_ASSERT(pSocket);
1852 if ( pSocket == 0 )
1854 OSL_TRACE("osl_sendSocket : Invalid socket");
1855 return -1;
1858 pSocket->m_nLastError=0;
1862 nWritten = send(pSocket->m_Socket,
1863 (sal_Char*)pBuffer,
1864 BytesToSend,
1865 MSG_FLAG_TO_NATIVE(Flag));
1866 } while ( nWritten < 0 && errno == EINTR );
1868 if ( nWritten < 0 )
1870 pSocket->m_nLastError=errno;
1871 OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,strerror(errno));
1873 else if ( nWritten == 0 )
1875 OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,"EOL");
1878 return nWritten;
1881 sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
1882 oslSocketAddr ReceiverAddr,
1883 const void* pBuffer,
1884 sal_uInt32 BytesToSend,
1885 oslSocketMsgFlag Flag)
1887 int nWritten;
1889 struct sockaddr *pSystemSockAddr = 0;
1890 int AddrLen = 0;
1891 if( ReceiverAddr )
1893 pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
1894 AddrLen = sizeof( struct sockaddr );
1897 OSL_ASSERT(pSocket);
1898 if ( pSocket == 0 )
1900 OSL_TRACE("osl_sendToSocket : Invalid socket");
1901 return -1;
1904 pSocket->m_nLastError=0;
1906 /* ReceiverAddr might be 0 when used on a connected socket. */
1907 /* Then sendto should behave like send. */
1909 nWritten = sendto(pSocket->m_Socket,
1910 (sal_Char*)pBuffer,
1911 BytesToSend,
1912 MSG_FLAG_TO_NATIVE(Flag),
1913 pSystemSockAddr,
1914 AddrLen);
1916 if ( nWritten < 0 )
1918 pSocket->m_nLastError=errno;
1919 OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,strerror(errno));
1921 else if ( nWritten == 0 )
1923 OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,"EOL");
1926 return nWritten;
1929 sal_Int32 SAL_CALL osl_readSocket (
1930 oslSocket pSocket, void *pBuffer, sal_Int32 n )
1932 sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
1933 sal_uInt32 BytesRead= 0;
1934 sal_uInt32 BytesToRead= n;
1936 OSL_ASSERT( pSocket);
1938 /* loop until all desired bytes were read or an error occurred */
1939 while (BytesToRead > 0)
1941 sal_Int32 RetVal;
1942 RetVal= osl_receiveSocket(pSocket,
1943 Ptr,
1944 BytesToRead,
1945 osl_Socket_MsgNormal);
1947 /* error occurred? */
1948 if(RetVal <= 0)
1950 break;
1953 BytesToRead -= RetVal;
1954 BytesRead += RetVal;
1955 Ptr += RetVal;
1958 return BytesRead;
1961 sal_Int32 SAL_CALL osl_writeSocket(
1962 oslSocket pSocket, const void *pBuffer, sal_Int32 n )
1964 /* loop until all desired bytes were send or an error occurred */
1965 sal_uInt32 BytesSend= 0;
1966 sal_uInt32 BytesToSend= n;
1967 sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer;
1969 OSL_ASSERT( pSocket );
1971 while (BytesToSend > 0)
1973 sal_Int32 RetVal;
1975 RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
1977 /* error occurred? */
1978 if(RetVal <= 0)
1980 break;
1983 BytesToSend -= RetVal;
1984 BytesSend += RetVal;
1985 Ptr += RetVal;
1988 return BytesSend;
1991 #ifdef HAVE_POLL_H /* poll() */
1993 sal_Bool __osl_socket_poll (
1994 oslSocket pSocket,
1995 const TimeValue* pTimeout,
1996 short nEvent)
1998 struct pollfd fds;
1999 int timeout;
2000 int result;
2002 OSL_ASSERT(0 != pSocket);
2003 if (0 == pSocket)
2004 return sal_False; /* EINVAL */
2006 pSocket->m_nLastError = 0;
2008 fds.fd = pSocket->m_Socket;
2009 fds.events = nEvent;
2010 fds.revents = 0;
2012 timeout = -1;
2013 if (pTimeout)
2015 /* Convert to [ms] */
2016 timeout = pTimeout->Seconds * 1000;
2017 timeout += pTimeout->Nanosec / (1000 * 1000);
2020 result = poll (&fds, 1, timeout);
2021 if (result < 0)
2023 pSocket->m_nLastError = errno;
2024 OSL_TRACE("__osl_socket_poll(): poll error: %d (%s)",
2025 errno, strerror(errno));
2026 return sal_False;
2028 if (result == 0)
2030 /* Timeout */
2031 return sal_False;
2034 return ((fds.revents & nEvent) == nEvent);
2037 #else /* select() */
2039 sal_Bool __osl_socket_poll (
2040 oslSocket pSocket,
2041 const TimeValue* pTimeout,
2042 short nEvent)
2044 fd_set fds;
2045 struct timeval tv;
2046 int result;
2048 OSL_ASSERT(0 != pSocket);
2049 if (0 == pSocket)
2050 return sal_False; /* EINVAL */
2052 pSocket->m_nLastError = 0;
2054 FD_ZERO(&fds);
2055 FD_SET(pSocket->m_Socket, &fds);
2057 if (pTimeout)
2059 /* Convert to 'timeval' */
2060 tv.tv_sec = pTimeout->Seconds;
2061 tv.tv_usec = pTimeout->Nanosec / 1000;
2064 result = select (
2065 pSocket->m_Socket + 1,
2066 (nEvent == POLLIN ) ? PTR_FD_SET(fds) : NULL,
2067 (nEvent == POLLOUT) ? PTR_FD_SET(fds) : NULL,
2068 (nEvent == POLLPRI) ? PTR_FD_SET(fds) : NULL,
2069 (pTimeout) ? &tv : NULL);
2071 if (result < 0)
2073 pSocket->m_nLastError = errno;
2074 OSL_TRACE("__osl_socket_poll(): select error: %d (%s)",
2075 errno, strerror(errno));
2076 return sal_False;
2078 if (result == 0)
2080 /* Timeout */
2081 return sal_False;
2084 return (FD_ISSET(pSocket->m_Socket, &fds) ? sal_True : sal_False);
2087 #endif /* HAVE_POLL_H */
2089 sal_Bool SAL_CALL osl_isReceiveReady (
2090 oslSocket pSocket, const TimeValue* pTimeout)
2092 OSL_ASSERT(pSocket);
2093 if (pSocket == NULL)
2095 /* ENOTSOCK */
2096 return sal_False;
2099 return __osl_socket_poll (pSocket, pTimeout, POLLIN);
2102 sal_Bool SAL_CALL osl_isSendReady (
2103 oslSocket pSocket, const TimeValue* pTimeout)
2105 OSL_ASSERT(pSocket);
2106 if (pSocket == NULL)
2108 /* ENOTSOCK */
2109 return sal_False;
2112 return __osl_socket_poll (pSocket, pTimeout, POLLOUT);
2115 sal_Bool SAL_CALL osl_isExceptionPending (
2116 oslSocket pSocket, const TimeValue* pTimeout)
2118 OSL_ASSERT(pSocket);
2119 if (pSocket == NULL)
2121 /* ENOTSOCK */
2122 return sal_False;
2125 return __osl_socket_poll (pSocket, pTimeout, POLLPRI);
2128 sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
2129 oslSocketDirection Direction)
2131 int nRet;
2133 OSL_ASSERT(pSocket);
2134 if ( pSocket == 0 )
2136 return sal_False;
2139 pSocket->m_nLastError=0;
2141 nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
2142 if (nRet != 0 )
2144 pSocket->m_nLastError=errno;
2145 OSL_TRACE("shutdown error '%s'",strerror(errno));
2147 return (nRet==0);
2150 sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
2151 oslSocketOptionLevel Level,
2152 oslSocketOption Option,
2153 void* pBuffer,
2154 sal_uInt32 BufferLen)
2156 socklen_t nOptLen = (socklen_t) BufferLen;
2158 OSL_ASSERT(pSocket);
2159 if ( pSocket == 0 )
2161 return -1;
2164 pSocket->m_nLastError=0;
2166 if(getsockopt(pSocket->m_Socket,
2167 OPTION_LEVEL_TO_NATIVE(Level),
2168 OPTION_TO_NATIVE(Option),
2169 (sal_Char*)pBuffer,
2170 &nOptLen) == -1)
2172 pSocket->m_nLastError=errno;
2173 return -1;
2176 return BufferLen;
2179 sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
2180 oslSocketOptionLevel Level,
2181 oslSocketOption Option,
2182 void* pBuffer,
2183 sal_uInt32 BufferLen)
2185 int nRet;
2187 OSL_ASSERT(pSocket);
2188 if ( pSocket == 0 )
2190 return sal_False;
2193 pSocket->m_nLastError=0;
2195 nRet = setsockopt(pSocket->m_Socket,
2196 OPTION_LEVEL_TO_NATIVE(Level),
2197 OPTION_TO_NATIVE(Option),
2198 (sal_Char*)pBuffer,
2199 BufferLen);
2201 if ( nRet < 0 )
2203 pSocket->m_nLastError=errno;
2204 return sal_False;
2207 return sal_True;
2210 sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
2211 sal_Bool On)
2213 int flags;
2214 int nRet;
2216 OSL_ASSERT(pSocket);
2217 if ( pSocket == 0 )
2219 return sal_False;
2222 pSocket->m_nLastError=0;
2224 flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
2226 if (On)
2227 flags |= O_NONBLOCK;
2228 else
2229 flags &= ~(O_NONBLOCK);
2231 nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
2233 if ( nRet < 0 )
2235 pSocket->m_nLastError=errno;
2236 return sal_False;
2239 return sal_True;
2242 sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
2244 int flags;
2246 OSL_ASSERT(pSocket);
2247 if ( pSocket == 0 )
2249 return sal_False;
2252 pSocket->m_nLastError=0;
2254 flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
2256 if (flags == -1 || !(flags & O_NONBLOCK))
2257 return sal_False;
2258 else
2259 return sal_True;
2262 oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
2264 int Type=0;
2265 socklen_t TypeSize= sizeof(Type);
2267 OSL_ASSERT(pSocket);
2268 if ( pSocket == 0 )
2270 return osl_Socket_TypeInvalid;
2273 pSocket->m_nLastError=0;
2275 if(getsockopt(pSocket->m_Socket,
2276 OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
2277 OPTION_TO_NATIVE(osl_Socket_OptionType),
2278 (sal_Char*)&Type,
2279 &TypeSize) == -1)
2281 /* error */
2282 pSocket->m_nLastError=errno;
2283 return osl_Socket_TypeInvalid;
2286 return TYPE_FROM_NATIVE(Type);
2290 void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
2292 sal_Char pszError[1024];
2294 pszError[0] = '\0';
2296 osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
2298 rtl_uString_newFromAscii(ustrError,pszError);
2300 return;
2303 void SAL_CALL osl_psz_getLastSocketErrorDescription(oslSocket pSocket, sal_Char* pBuffer, sal_uInt32 BufferSize)
2305 /* make sure pBuffer will be a zero-terminated string even when strncpy has to cut */
2306 pBuffer[BufferSize-1]= '\0';
2308 if ( pSocket == 0 )
2310 strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
2311 return;
2314 strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
2315 return;
2318 oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
2320 if ( pSocket == 0 )
2322 return ERROR_FROM_NATIVE(EINVAL);
2325 return ERROR_FROM_NATIVE(pSocket->m_nLastError);
2328 typedef struct _TSocketSetImpl
2330 int m_MaxHandle; /* for select(), the largest descriptor in the set */
2331 fd_set m_Set; /* the set of descriptors */
2333 } TSocketSetImpl;
2335 oslSocketSet SAL_CALL osl_createSocketSet()
2337 TSocketSetImpl* pSet;
2339 pSet= (TSocketSetImpl*)malloc(sizeof(TSocketSetImpl));
2341 OSL_ASSERT(pSet);
2343 if(pSet)
2345 pSet->m_MaxHandle= 0;
2346 FD_ZERO(&pSet->m_Set);
2349 return (oslSocketSet)pSet;
2352 void SAL_CALL osl_destroySocketSet(oslSocketSet Set)
2354 if(Set)
2355 free(Set);
2358 void SAL_CALL osl_clearSocketSet(oslSocketSet Set)
2360 TSocketSetImpl* pSet;
2361 OSL_ASSERT(Set);
2362 if ( Set == 0 )
2364 return;
2367 pSet= (TSocketSetImpl*)Set;
2368 pSet->m_MaxHandle= 0;
2370 FD_ZERO(&pSet->m_Set);
2373 void SAL_CALL osl_addToSocketSet(oslSocketSet Set, oslSocket pSocket)
2375 TSocketSetImpl* pSet;
2377 OSL_ASSERT(Set);
2378 OSL_ASSERT(pSocket);
2380 if ( Set == 0 || pSocket == 0)
2382 return;
2385 pSet= (TSocketSetImpl*)Set;
2387 /* correct max handle */
2388 if(pSocket->m_Socket > pSet->m_MaxHandle)
2389 pSet->m_MaxHandle= pSocket->m_Socket;
2390 FD_SET(pSocket->m_Socket, &pSet->m_Set);
2394 void SAL_CALL osl_removeFromSocketSet(oslSocketSet Set, oslSocket pSocket)
2396 TSocketSetImpl* pSet;
2398 OSL_ASSERT(Set);
2399 OSL_ASSERT(pSocket);
2401 if ( Set == 0 || pSocket == 0)
2403 return;
2406 pSet= (TSocketSetImpl*)Set;
2408 /* correct max handle */
2409 if(pSocket->m_Socket == pSet->m_MaxHandle)
2411 /* not optimal, since the next used descriptor might be */
2412 /* much smaller than m_Socket-1, but it will do */
2413 pSet->m_MaxHandle--;
2414 if(pSet->m_MaxHandle < 0)
2416 pSet->m_MaxHandle= 0; /* avoid underflow */
2420 FD_CLR(pSocket->m_Socket, &pSet->m_Set);
2423 sal_Bool SAL_CALL osl_isInSocketSet(oslSocketSet Set, oslSocket pSocket)
2425 TSocketSetImpl* pSet;
2427 OSL_ASSERT(Set);
2428 OSL_ASSERT(pSocket);
2429 if ( Set == 0 || pSocket == 0 )
2431 return sal_False;
2434 pSet= (TSocketSetImpl*)Set;
2436 return (FD_ISSET(pSocket->m_Socket, &pSet->m_Set) != 0);
2439 sal_Int32 SAL_CALL osl_demultiplexSocketEvents(oslSocketSet IncomingSet,
2440 oslSocketSet OutgoingSet,
2441 oslSocketSet OutOfBandSet,
2442 const TimeValue* pTimeout)
2444 int MaxHandle= 0;
2445 struct timeval tv;
2446 TSocketSetImpl* pInSet;
2447 TSocketSetImpl* pOutSet;
2448 TSocketSetImpl* pOOBSet;
2450 if (pTimeout)
2452 /* non-blocking call */
2453 tv.tv_sec = pTimeout->Seconds;
2454 tv.tv_usec = pTimeout->Nanosec / 1000L;
2457 /* map opaque data to impl-types */
2458 pInSet= (TSocketSetImpl*)IncomingSet;
2459 pOutSet= (TSocketSetImpl*)OutgoingSet;
2460 pOOBSet= (TSocketSetImpl*)OutOfBandSet;
2462 /* get max handle from all sets */
2463 if (pInSet)
2464 MaxHandle= pInSet->m_MaxHandle;
2466 if (pOutSet && (pOutSet->m_MaxHandle > MaxHandle))
2467 MaxHandle= pOutSet->m_MaxHandle;
2469 if (pOOBSet && (pOOBSet->m_MaxHandle > MaxHandle))
2470 MaxHandle= pOOBSet->m_MaxHandle;
2472 return select(MaxHandle+1,
2473 pInSet ? PTR_FD_SET(pInSet->m_Set) : 0,
2474 pOutSet ? PTR_FD_SET(pOutSet->m_Set) : 0,
2475 pOOBSet ? PTR_FD_SET(pOOBSet->m_Set) : 0,
2476 pTimeout ? &tv : 0);
2479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */