Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "system.h"
21 :
22 : #include <osl/socket.h>
23 : #include <osl/diagnose.h>
24 : #include <osl/mutex.h>
25 : #include <osl/signal.h>
26 :
27 : #include <rtl/alloc.h>
28 : #include <assert.h>
29 : #include <ctype.h>
30 : #include <sal/types.h>
31 :
32 : #include "sockimpl.h"
33 :
34 : /* defines for poll */
35 : #ifdef HAVE_POLL_H
36 : #undef HAVE_POLL_H
37 : #endif
38 :
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 */
44 :
45 : #if defined(SOLARIS)
46 : #include <poll.h>
47 : #define HAVE_POLL_H
48 : #endif /* SOLARIS */
49 :
50 : #ifndef HAVE_POLL_H
51 : #define POLLIN 0x0001
52 : #define POLLOUT 0x0002
53 : #define POLLPRI 0x0004
54 : #endif /* HAVE_POLL_H */
55 :
56 : /* defines for shutdown */
57 : #define SD_RECEIVE 0
58 : #define SD_SEND 1
59 : #define SD_BOTH 2
60 :
61 : /*
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.
67 :
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).
72 :
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).
79 : */
80 :
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. */
84 :
85 : #define OSL_INVALID_SOCKET -1
86 : #define OSL_SOCKET_ERROR -1
87 :
88 : /* Buffer size for gethostbyname */
89 : #define MAX_HOSTBUFFER_SIZE 2048
90 :
91 : /*****************************************************************************/
92 : /* enum oslAddrFamily */
93 : /*****************************************************************************/
94 :
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 */
100 : };
101 :
102 : /* reverse map */
103 0 : static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
104 : {
105 0 : oslAddrFamily i= (oslAddrFamily)0;
106 :
107 0 : while(i != osl_Socket_FamilyInvalid)
108 : {
109 0 : if(FamilyMap[i] == nativeType)
110 0 : return i;
111 0 : i = (oslAddrFamily) ( i + 1 );
112 : }
113 :
114 0 : return i;
115 : }
116 :
117 : /* macros */
118 : #define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
119 : #define FAMILY_TO_NATIVE(x) (short)FamilyMap[x]
120 :
121 : /*****************************************************************************/
122 : /* enum oslProtocol */
123 : /*****************************************************************************/
124 :
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 */
132 : };
133 :
134 : /* reverse map */
135 : /* mfe: NOT USED
136 : static oslProtocol osl_ProtocolFromNative(sal_uInt32 nativeType)
137 : {
138 : oslProtocol i= (oslProtocol)0;
139 :
140 : while(i != osl_Socket_ProtocolInvalid)
141 : {
142 : if(ProtocolMap[i] == nativeType)
143 : return i;
144 : i = (oslProtocol) ( i + 1);
145 : }
146 :
147 : return i;
148 : }
149 : */
150 :
151 : /* macros */
152 : #define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
153 :
154 : /*****************************************************************************/
155 : /* enum oslSocketType */
156 : /*****************************************************************************/
157 :
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 */
166 : };
167 :
168 : /* reverse map */
169 0 : static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType)
170 : {
171 0 : oslSocketType i= (oslSocketType)0;
172 :
173 0 : while(i != osl_Socket_TypeInvalid)
174 : {
175 0 : if(TypeMap[i] == nativeType)
176 0 : return i;
177 0 : i = (oslSocketType)(i + 1);
178 : }
179 :
180 0 : return i;
181 : }
182 :
183 : /* macros */
184 : #define TYPE_TO_NATIVE(x) TypeMap[x]
185 : #define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
186 :
187 : /*****************************************************************************/
188 : /* enum oslSocketOption */
189 : /*****************************************************************************/
190 :
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 */
212 : };
213 :
214 : /* reverse map */
215 : /* mfe: NOT USED
216 : static oslSocketOption osl_SocketOptionFromNative(sal_uInt32 nativeType)
217 : {
218 : oslSocketOption i= (oslSocketOption)0;
219 :
220 : while(i != osl_Socket_OptionInvalid)
221 : {
222 : if(OptionMap[i] == nativeType)
223 : return i;
224 : i = (oslSocketOption) ( i + 1 );
225 : }
226 :
227 : return i;
228 : }
229 : */
230 : /* macros */
231 : #define OPTION_TO_NATIVE(x) OptionMap[x]
232 :
233 : /*****************************************************************************/
234 : /* enum oslSocketOptionLevel */
235 : /*****************************************************************************/
236 :
237 : static const sal_uInt32 OptionLevelMap[]= {
238 : SOL_SOCKET, /* osl_Socket_LevelSocket */
239 : IPPROTO_TCP, /* osl_Socket_LevelTcp */
240 : 0 /* osl_Socket_LevelInvalid */
241 : };
242 :
243 : /* reverse map */
244 : /* mfe: NOT USED
245 : static oslSocketOptionLevel osl_SocketOptionLevelFromNative(sal_uInt32 nativeType)
246 : {
247 : oslSocketOptionLevel i= (oslSocketOptionLevel)0;
248 :
249 : while(i != osl_Socket_LevelInvalid)
250 : {
251 : if(OptionLevelMap[i] == nativeType)
252 : return i;
253 : i = (oslSocketOptionLevel) ( i + 1 );
254 : }
255 :
256 : return i;
257 : }
258 : */
259 : /* macros */
260 : #define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
261 :
262 : /*****************************************************************************/
263 : /* enum oslSocketMsgFlag */
264 : /*****************************************************************************/
265 :
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 */
273 : };
274 :
275 : /* reverse map */
276 : /* mfe: NOT USED
277 : static oslSocketMsgFlag osl_SocketMsgFlagFromNative(sal_uInt32 nativeType)
278 : {
279 : oslSocketMsgFlag i= (oslSocketMsgFlag)0;
280 :
281 : while(i != osl_Socket_MsgInvalid)
282 : {
283 : if(SocketMsgFlagMap[i] == nativeType)
284 : return i;
285 : i = (oslSocketMsgFlag) ( i + 1 );
286 : }
287 :
288 : return i;
289 : }
290 : */
291 :
292 : /* macros */
293 : #define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
294 :
295 : /*****************************************************************************/
296 : /* enum oslSocketDirection */
297 : /*****************************************************************************/
298 :
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 */
304 : };
305 :
306 : /* reverse map */
307 : /* mfe: NOT USED
308 : static oslSocketDirection osl_SocketDirectionFromNative(sal_uInt32 nativeType)
309 : {
310 : oslSocketDirection i= (oslSocketDirection)0;
311 :
312 : while(i != osl_Socket_DirInvalid)
313 : {
314 : if(SocketDirection[i] == nativeType)
315 : return i;
316 : i = (oslSocketDirection) ( i + 1 );
317 : }
318 :
319 : return i;
320 : }
321 : */
322 :
323 : /* macros */
324 : #define DIRECTION_TO_NATIVE(x) SocketDirection[x]
325 :
326 : /*****************************************************************************/
327 : /* enum oslSocketError */
328 : /*****************************************************************************/
329 :
330 : static const struct
331 : {
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 }
369 : };
370 :
371 : /* map */
372 : /* mfe: NOT USED
373 : static int osl_NativeFromSocketError(oslSocketError errorCode)
374 : {
375 : int i = 0;
376 :
377 : while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
378 : (SocketError[i].error != errorCode)) i++;
379 :
380 : return SocketError[i].errcode;
381 : }
382 : */
383 :
384 : /* reverse map */
385 0 : static oslSocketError osl_SocketErrorFromNative(int nativeType)
386 : {
387 0 : int i = 0;
388 :
389 0 : while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
390 0 : (SocketError[i].errcode != nativeType)) i++;
391 :
392 0 : return SocketError[i].error;
393 : }
394 :
395 : /* macros */
396 : #define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
397 :
398 : /*****************************************************************************/
399 : /* local function prototypes */
400 : /*****************************************************************************/
401 :
402 : oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
403 : const sal_Char* pszDottedAddr, sal_Int32 Port);
404 :
405 : oslHostAddr SAL_CALL osl_psz_createHostAddr (
406 : const sal_Char *pszHostname, const oslSocketAddr Addr);
407 :
408 : oslHostAddr SAL_CALL osl_psz_createHostAddrByName (
409 : const sal_Char *pszHostname);
410 :
411 : const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (
412 : const oslHostAddr Addr);
413 :
414 : oslSocketResult SAL_CALL osl_psz_getLocalHostname (
415 : sal_Char *pBuffer, sal_uInt32 nBufLen);
416 :
417 : oslSocketAddr SAL_CALL osl_psz_resolveHostname (
418 : const sal_Char* pszHostname);
419 :
420 : sal_Int32 SAL_CALL osl_psz_getServicePort (
421 : const sal_Char* pszServicename, const sal_Char* pszProtocol);
422 :
423 : oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr (
424 : oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
425 :
426 : oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr (
427 : oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
428 :
429 : void SAL_CALL osl_psz_getLastSocketErrorDescription (
430 : oslSocket Socket, sal_Char* pBuffer, sal_uInt32 BufferSize);
431 :
432 : #if OSL_DEBUG_LEVEL > 1
433 : static sal_uInt32 g_nSocketImpl = 0;
434 : static sal_uInt32 g_nSocketAddr = 0;
435 :
436 : /* sorry, must be implemented otherwise */
437 :
438 : #endif /* OSL_DEBUG_LEVEL */
439 :
440 0 : oslSocket __osl_createSocketImpl(int Socket)
441 : {
442 : oslSocket pSocket;
443 :
444 0 : pSocket = (oslSocket)calloc(1, sizeof(struct oslSocketImpl));
445 :
446 0 : pSocket->m_Socket = Socket;
447 0 : pSocket->m_nLastError = 0;
448 0 : pSocket->m_nRefCount = 1;
449 :
450 : #if defined(LINUX)
451 0 : pSocket->m_bIsAccepting = sal_False;
452 : #endif
453 :
454 : #if OSL_DEBUG_LEVEL > 1
455 : g_nSocketImpl ++;
456 : #endif
457 0 : return pSocket;
458 : }
459 :
460 0 : void __osl_destroySocketImpl(oslSocket Socket)
461 : {
462 0 : if ( Socket != NULL)
463 0 : free((struct oslSocketImpl *) Socket);
464 : #if OSL_DEBUG_LEVEL > 1
465 : g_nSocketImpl --;
466 : #endif
467 0 : }
468 :
469 0 : static oslSocketAddr __osl_createSocketAddr(void)
470 : {
471 0 : oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
472 : #if OSL_DEBUG_LEVEL > 1
473 : g_nSocketAddr ++;
474 : #endif
475 0 : return pAddr;
476 : }
477 :
478 0 : static oslSocketAddr __osl_createSocketAddrWithFamily(
479 : oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
480 : {
481 : oslSocketAddr pAddr;
482 :
483 : OSL_ASSERT( family == osl_Socket_FamilyInet );
484 :
485 0 : pAddr = __osl_createSocketAddr();
486 0 : switch( family )
487 : {
488 : case osl_Socket_FamilyInet:
489 : {
490 0 : struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
491 :
492 0 : pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
493 0 : pInetAddr->sin_addr.s_addr = nAddr;
494 0 : pInetAddr->sin_port = (sal_uInt16)(port&0xffff);
495 0 : break;
496 : }
497 : default:
498 0 : pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
499 : }
500 0 : return pAddr;
501 : }
502 :
503 0 : static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
504 : {
505 0 : oslSocketAddr pAddr = __osl_createSocketAddr();
506 0 : memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) );
507 0 : return pAddr;
508 : }
509 :
510 0 : static void __osl_destroySocketAddr( oslSocketAddr addr )
511 : {
512 : #if OSL_DEBUG_LEVEL > 1
513 : g_nSocketAddr --;
514 : #endif
515 0 : rtl_freeMemory( addr );
516 0 : }
517 :
518 0 : oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
519 : {
520 0 : oslSocketAddr pAddr = 0;
521 :
522 : /* is it an internet-Addr? */
523 0 : if (Family == osl_Socket_FamilyInet)
524 : {
525 0 : pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
526 : }
527 : else
528 : {
529 0 : pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 );
530 : }
531 :
532 0 : return pAddr;
533 : }
534 :
535 0 : oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
536 : {
537 0 : oslSocketAddr pCopy = 0;
538 0 : if (Addr)
539 : {
540 0 : pCopy = __osl_createSocketAddr();
541 :
542 0 : if (pCopy)
543 0 : memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
544 : }
545 0 : return pCopy;
546 : }
547 :
548 0 : sal_Bool SAL_CALL osl_isEqualSocketAddr (
549 : oslSocketAddr Addr1,
550 : oslSocketAddr Addr2)
551 : {
552 0 : struct sockaddr* pAddr1 = NULL;
553 0 : struct sockaddr* pAddr2 = NULL;
554 :
555 : assert(Addr1 && Addr2);
556 0 : pAddr1 = &(Addr1->m_sockaddr);
557 0 : pAddr2 = &(Addr2->m_sockaddr);
558 :
559 0 : if (pAddr1 == pAddr2)
560 : {
561 0 : return (sal_True);
562 : }
563 :
564 0 : if (pAddr1->sa_family == pAddr2->sa_family)
565 : {
566 0 : switch (pAddr1->sa_family)
567 : {
568 : case AF_INET:
569 : {
570 0 : struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1;
571 0 : struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2;
572 :
573 0 : if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
574 0 : (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
575 0 : (pInetAddr1->sin_port == pInetAddr2->sin_port))
576 0 : return (sal_True);
577 : }
578 :
579 : default:
580 : {
581 0 : return (memcmp(pAddr1, pAddr2, sizeof(struct sockaddr)) == 0);
582 : }
583 : }
584 : }
585 :
586 0 : return (sal_False);
587 : }
588 :
589 0 : oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
590 : rtl_uString *strDottedAddr,
591 : sal_Int32 Port)
592 : {
593 0 : sal_uInt32 nAddr = OSL_INADDR_NONE;
594 : oslSocketAddr pAddr;
595 :
596 0 : if (strDottedAddr && strDottedAddr->length)
597 : {
598 : /* Dotted host address for limited broadcast */
599 0 : rtl_String *pDottedAddr = NULL;
600 :
601 0 : rtl_uString2String (
602 0 : &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
603 : RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
604 :
605 0 : nAddr = inet_addr (pDottedAddr->buffer);
606 0 : rtl_string_release (pDottedAddr);
607 : }
608 :
609 0 : if (nAddr != OSL_INADDR_NONE)
610 : {
611 : /* Limited broadcast */
612 0 : nAddr = ntohl(nAddr);
613 0 : if (IN_CLASSA(nAddr))
614 : {
615 0 : nAddr &= IN_CLASSA_NET;
616 0 : nAddr |= IN_CLASSA_HOST;
617 : }
618 0 : else if (IN_CLASSB(nAddr))
619 : {
620 0 : nAddr &= IN_CLASSB_NET;
621 0 : nAddr |= IN_CLASSB_HOST;
622 : }
623 0 : else if (IN_CLASSC(nAddr))
624 : {
625 0 : nAddr &= IN_CLASSC_NET;
626 0 : nAddr |= IN_CLASSC_HOST;
627 : }
628 : else
629 : {
630 : /* No broadcast in class D */
631 0 : return ((oslSocketAddr)NULL);
632 : }
633 0 : nAddr = htonl(nAddr);
634 : }
635 :
636 0 : pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
637 0 : return pAddr;
638 : }
639 :
640 0 : oslSocketAddr SAL_CALL osl_createInetSocketAddr (
641 : rtl_uString *ustrDottedAddr,
642 : sal_Int32 Port)
643 : {
644 0 : rtl_String* strDottedAddr=0;
645 : oslSocketAddr Addr;
646 0 : sal_Char* pszDottedAddr=0;
647 :
648 0 : if ( ustrDottedAddr != 0 )
649 : {
650 0 : rtl_uString2String( &strDottedAddr,
651 0 : rtl_uString_getStr(ustrDottedAddr),
652 : rtl_uString_getLength(ustrDottedAddr),
653 : RTL_TEXTENCODING_UTF8,
654 : OUSTRING_TO_OSTRING_CVTFLAGS);
655 0 : pszDottedAddr = rtl_string_getStr(strDottedAddr);
656 : }
657 :
658 0 : Addr = pszDottedAddr ? osl_psz_createInetSocketAddr(pszDottedAddr, Port) : 0;
659 :
660 0 : if ( strDottedAddr != 0 )
661 : {
662 0 : rtl_string_release(strDottedAddr);
663 : }
664 :
665 0 : return Addr;
666 : }
667 :
668 0 : oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
669 : const sal_Char* pszDottedAddr,
670 : sal_Int32 Port)
671 : {
672 0 : oslSocketAddr pAddr = 0;
673 0 : sal_Int32 Addr = inet_addr(pszDottedAddr);
674 0 : if(Addr != -1)
675 : {
676 : /* valid dotted addr */
677 0 : pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , Addr );
678 : }
679 0 : return pAddr;
680 : }
681 :
682 0 : oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
683 : {
684 0 : oslSocketResult res = osl_Socket_Error;
685 :
686 : OSL_ASSERT( pAddr );
687 : OSL_ASSERT( pByteSeq );
688 :
689 0 : if( pAddr && pByteSeq )
690 : {
691 : struct sockaddr_in * pSystemInetAddr;
692 :
693 : OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
694 : OSL_ASSERT( pByteSeq->nElements == 4 );
695 :
696 0 : pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
697 0 : memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
698 0 : res = osl_Socket_Ok;
699 : }
700 0 : return res;
701 : }
702 :
703 0 : oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
704 : {
705 0 : oslSocketResult res = osl_Socket_Error;
706 :
707 : OSL_ASSERT( pAddr );
708 : OSL_ASSERT( ppByteSeq );
709 :
710 0 : if( pAddr && ppByteSeq )
711 : {
712 0 : struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
713 0 : rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4);
714 0 : res = osl_Socket_Ok;
715 : }
716 0 : return res;
717 : }
718 :
719 : /** try to figure out a full-qualified hostname, by adding the current domain
720 : as given by the domainname program to the given hostname.
721 : This function MUST NOT call gethostbyname since pHostName already points
722 : to data returned by gethostname and would be garbled: use gethostname_r
723 : instead!
724 : */
725 :
726 : /* wrap around different interfaces to reentrant gethostbyname */
727 0 : static struct hostent* _osl_gethostbyname_r (
728 : const char *name, struct hostent *result,
729 : char *buffer, int buflen, int *h_errnop)
730 : {
731 : #if defined(LINUX) || defined(ANDROID) || defined(FREEBSD) || defined(DRAGONFLY)
732 : struct hostent *__result; /* will be the same as result */
733 : int __error;
734 0 : __error = gethostbyname_r (name, result, buffer, buflen,
735 : &__result, h_errnop);
736 0 : return __error ? NULL : __result ;
737 : #elif defined(AIX)
738 : *h_errnop = gethostbyname_r (name, result, (struct hostent_data *)buffer);
739 : (void)buflen;
740 : return *h_errnop ? NULL : result ;
741 : #else
742 : return gethostbyname_r( name, result, buffer, buflen, h_errnop);
743 : #endif
744 : }
745 :
746 0 : static sal_Char* _osl_getFullQualifiedDomainName (const sal_Char *pHostName)
747 : {
748 : struct hostent aHostByName;
749 : struct hostent *pHostByName;
750 : sal_Char pQualifiedHostBuffer[ MAX_HOSTBUFFER_SIZE ];
751 0 : sal_Char *pFullQualifiedName = NULL;
752 : int nErrorNo;
753 :
754 0 : pHostByName = _osl_gethostbyname_r (
755 : pHostName,
756 : &aHostByName, pQualifiedHostBuffer,
757 : sizeof(pQualifiedHostBuffer), &nErrorNo );
758 0 : if (pHostByName != NULL)
759 : {
760 0 : pFullQualifiedName = strdup(pHostByName->h_name);
761 : }
762 0 : return pFullQualifiedName;
763 : }
764 :
765 0 : static sal_Bool _osl_isFullQualifiedDomainName (const sal_Char *pHostName)
766 : {
767 : /* a FQDN (aka 'hostname.domain.top_level_domain' )
768 : * is a name which contains a dot '.' in it ( would
769 : * match as well for 'hostname.' but is good enough
770 : * for now )*/
771 0 : return (sal_Bool)( strchr( pHostName, (int)'.' ) != NULL );
772 : }
773 :
774 : struct oslHostAddrImpl
775 : {
776 : sal_Char *pHostName;
777 : oslSocketAddr pSockAddr;
778 : };
779 :
780 0 : static oslHostAddr _osl_hostentToHostAddr (const struct hostent *he)
781 : {
782 0 : oslHostAddr pAddr= NULL;
783 0 : oslSocketAddr pSockAddr = 0;
784 :
785 : sal_Char *cn;
786 :
787 0 : if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
788 0 : return ((oslHostAddr)NULL);
789 :
790 0 : if (_osl_isFullQualifiedDomainName(he->h_name))
791 : {
792 0 : cn= strdup(he->h_name);
793 : OSL_ASSERT(cn);
794 0 : if (cn == NULL)
795 0 : return ((oslHostAddr)NULL);
796 : }
797 : else
798 : {
799 0 : cn =_osl_getFullQualifiedDomainName (he->h_name);
800 : OSL_ASSERT(cn);
801 0 : if (cn == NULL)
802 0 : return ((oslHostAddr)NULL);
803 : }
804 :
805 0 : pSockAddr = __osl_createSocketAddr();
806 : OSL_ASSERT(pSockAddr);
807 0 : if (pSockAddr == NULL)
808 : {
809 0 : free(cn);
810 0 : return ((oslHostAddr)NULL);
811 : }
812 :
813 0 : pSockAddr->m_sockaddr.sa_family= he->h_addrtype;
814 0 : if (pSockAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
815 : {
816 0 : struct sockaddr_in *sin= (struct sockaddr_in *)&(pSockAddr->m_sockaddr);
817 0 : memcpy (
818 0 : &(sin->sin_addr.s_addr),
819 0 : he->h_addr_list[0],
820 0 : he->h_length);
821 : }
822 : else
823 : {
824 : /* unknown address family */
825 : /* future extensions for new families might be implemented here */
826 :
827 : OSL_TRACE("_osl_hostentToHostAddr: unknown address family.");
828 : OSL_ASSERT(sal_False);
829 :
830 0 : __osl_destroySocketAddr( pSockAddr );
831 0 : free (cn);
832 0 : return ((oslHostAddr)NULL);
833 : }
834 :
835 0 : pAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
836 : OSL_ASSERT(pAddr);
837 0 : if (pAddr == NULL)
838 : {
839 0 : __osl_destroySocketAddr( pSockAddr );
840 0 : free (cn);
841 0 : return ((oslHostAddr)NULL);
842 : }
843 :
844 0 : pAddr->pHostName= cn;
845 0 : pAddr->pSockAddr= pSockAddr;
846 :
847 0 : return pAddr;
848 : }
849 :
850 0 : oslHostAddr SAL_CALL osl_createHostAddr (
851 : rtl_uString *ustrHostname,
852 : const oslSocketAddr Addr)
853 : {
854 : oslHostAddr HostAddr;
855 0 : rtl_String* strHostname=0;
856 0 : sal_Char* pszHostName=0;
857 :
858 0 : if ( ustrHostname != 0 )
859 : {
860 0 : rtl_uString2String( &strHostname,
861 0 : rtl_uString_getStr(ustrHostname),
862 : rtl_uString_getLength(ustrHostname),
863 : RTL_TEXTENCODING_UTF8,
864 : OUSTRING_TO_OSTRING_CVTFLAGS );
865 0 : pszHostName = rtl_string_getStr(strHostname);
866 : }
867 :
868 0 : HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
869 :
870 0 : if ( strHostname != 0 )
871 : {
872 0 : rtl_string_release(strHostname);
873 : }
874 :
875 0 : return HostAddr;
876 : }
877 :
878 0 : oslHostAddr SAL_CALL osl_psz_createHostAddr (
879 : const sal_Char *pszHostname,
880 : const oslSocketAddr pAddr)
881 : {
882 : oslHostAddr pHostAddr;
883 : sal_Char *cn;
884 :
885 : OSL_ASSERT(pszHostname && pAddr);
886 0 : if ((pszHostname == NULL) || (pAddr == NULL))
887 0 : return ((oslHostAddr)NULL);
888 :
889 0 : cn = strdup(pszHostname);
890 : OSL_ASSERT(cn);
891 0 : if (cn == NULL)
892 0 : return ((oslHostAddr)NULL);
893 :
894 0 : pHostAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
895 : OSL_ASSERT(pHostAddr);
896 0 : if (pHostAddr == NULL)
897 : {
898 0 : free (cn);
899 0 : return ((oslHostAddr)NULL);
900 : }
901 :
902 0 : pHostAddr->pHostName= cn;
903 0 : pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
904 :
905 0 : return pHostAddr;
906 : }
907 :
908 0 : oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
909 : {
910 : oslHostAddr HostAddr;
911 0 : rtl_String* strHostname=0;
912 0 : sal_Char* pszHostName=0;
913 :
914 0 : if ( ustrHostname != 0 )
915 : {
916 0 : rtl_uString2String( &strHostname,
917 0 : rtl_uString_getStr(ustrHostname),
918 : rtl_uString_getLength(ustrHostname),
919 : RTL_TEXTENCODING_UTF8,
920 : OUSTRING_TO_OSTRING_CVTFLAGS );
921 0 : pszHostName=rtl_string_getStr(strHostname);
922 : }
923 :
924 0 : HostAddr = osl_psz_createHostAddrByName(pszHostName);
925 :
926 0 : if ( strHostname != 0 )
927 : {
928 0 : rtl_string_release(strHostname);
929 : }
930 :
931 0 : return HostAddr;
932 : }
933 :
934 0 : oslHostAddr SAL_CALL osl_psz_createHostAddrByName (const sal_Char *pszHostname)
935 : {
936 : struct hostent aHe;
937 : struct hostent *pHe;
938 : sal_Char heBuffer[ MAX_HOSTBUFFER_SIZE ];
939 : int nErrorNo;
940 :
941 0 : pHe = _osl_gethostbyname_r (
942 : pszHostname,
943 : &aHe, heBuffer,
944 : sizeof(heBuffer), &nErrorNo );
945 :
946 0 : return _osl_hostentToHostAddr (pHe);
947 : }
948 :
949 0 : oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
950 : {
951 : OSL_ASSERT(pAddr);
952 :
953 0 : if (pAddr == NULL)
954 0 : return ((oslHostAddr)NULL);
955 :
956 0 : if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
957 : {
958 0 : const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr);
959 : struct hostent *he;
960 :
961 0 : if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
962 0 : return ((oslHostAddr)NULL);
963 :
964 0 : he= gethostbyaddr((sal_Char *)&(sin->sin_addr),
965 : sizeof (sin->sin_addr),
966 0 : sin->sin_family);
967 0 : return _osl_hostentToHostAddr (he);
968 : }
969 :
970 0 : return ((oslHostAddr)NULL);
971 : }
972 :
973 0 : oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr)
974 : {
975 : OSL_ASSERT(pAddr);
976 :
977 0 : if (pAddr)
978 0 : return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
979 : else
980 0 : return ((oslHostAddr)NULL);
981 : }
982 :
983 0 : void SAL_CALL osl_getHostnameOfHostAddr (
984 : const oslHostAddr Addr,
985 : rtl_uString **ustrHostname)
986 : {
987 0 : const sal_Char* pHostname=0;
988 :
989 0 : pHostname = osl_psz_getHostnameOfHostAddr(Addr);
990 :
991 0 : rtl_uString_newFromAscii (ustrHostname, pHostname);
992 :
993 0 : return;
994 : }
995 :
996 0 : const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
997 : {
998 0 : if (pAddr)
999 0 : return pAddr->pHostName;
1000 : else
1001 0 : return NULL;
1002 : }
1003 :
1004 0 : oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
1005 : {
1006 : OSL_ASSERT(pAddr);
1007 :
1008 0 : if (pAddr)
1009 0 : return ((oslSocketAddr)(pAddr->pSockAddr));
1010 : else
1011 0 : return NULL;
1012 : }
1013 :
1014 0 : void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
1015 : {
1016 0 : if (pAddr)
1017 : {
1018 0 : if (pAddr->pHostName)
1019 0 : free (pAddr->pHostName);
1020 0 : if (pAddr->pSockAddr)
1021 0 : osl_destroySocketAddr (pAddr->pSockAddr);
1022 0 : free (pAddr);
1023 : }
1024 0 : }
1025 :
1026 396 : oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
1027 : {
1028 : oslSocketResult Result;
1029 : sal_Char pszHostname[1024];
1030 :
1031 396 : pszHostname[0] = '\0';
1032 :
1033 396 : Result = osl_psz_getLocalHostname(pszHostname,sizeof(pszHostname));
1034 :
1035 396 : rtl_uString_newFromAscii(ustrLocalHostname,pszHostname);
1036 :
1037 396 : return Result;
1038 : }
1039 :
1040 396 : oslSocketResult SAL_CALL osl_psz_getLocalHostname (
1041 : sal_Char *pBuffer, sal_uInt32 nBufLen)
1042 : {
1043 : static sal_Char LocalHostname[256] = "";
1044 :
1045 396 : if (strlen(LocalHostname) == 0)
1046 : {
1047 : const sal_Char *pStr;
1048 :
1049 : #ifdef SYSV
1050 : struct utsname uts;
1051 :
1052 : if (uname(&uts) < 0)
1053 : return osl_Socket_Error;
1054 :
1055 : if ((strlen(uts.nodename) + 1) > nBufLen)
1056 : return osl_Socket_Error;
1057 :
1058 : strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
1059 : #else /* BSD compatible */
1060 30 : if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
1061 0 : return osl_Socket_Error;
1062 : #endif /* SYSV */
1063 30 : LocalHostname[sizeof(LocalHostname)-1] = 0;
1064 :
1065 : /* check if we have an FQDN */
1066 30 : if (strchr(LocalHostname, '.') == NULL)
1067 : {
1068 : oslHostAddr Addr;
1069 :
1070 : /* no, determine it via dns */
1071 0 : Addr = osl_psz_createHostAddrByName(LocalHostname);
1072 :
1073 0 : if ((pStr = osl_psz_getHostnameOfHostAddr(Addr)) != NULL)
1074 : {
1075 0 : strncpy(LocalHostname, pStr, sizeof( LocalHostname ));
1076 0 : LocalHostname[sizeof(LocalHostname)-1] = 0;
1077 : }
1078 0 : osl_destroyHostAddr(Addr);
1079 : }
1080 : }
1081 :
1082 396 : if (strlen(LocalHostname) > 0)
1083 : {
1084 396 : strncpy(pBuffer, LocalHostname, nBufLen);
1085 396 : pBuffer[nBufLen - 1] = '\0';
1086 :
1087 396 : return osl_Socket_Ok;
1088 : }
1089 :
1090 0 : return osl_Socket_Error;
1091 : }
1092 :
1093 0 : oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
1094 : {
1095 : oslSocketAddr Addr;
1096 0 : rtl_String* strHostname=0;
1097 0 : sal_Char* pszHostName=0;
1098 :
1099 0 : if ( ustrHostname != 0 )
1100 : {
1101 0 : rtl_uString2String( &strHostname,
1102 0 : rtl_uString_getStr(ustrHostname),
1103 : rtl_uString_getLength(ustrHostname),
1104 : RTL_TEXTENCODING_UTF8,
1105 : OUSTRING_TO_OSTRING_CVTFLAGS );
1106 0 : pszHostName = rtl_string_getStr(strHostname);
1107 : }
1108 :
1109 0 : Addr = osl_psz_resolveHostname(pszHostName);
1110 :
1111 0 : if ( strHostname != 0 )
1112 : {
1113 0 : rtl_string_release(strHostname);
1114 : }
1115 :
1116 0 : return Addr;
1117 : }
1118 :
1119 0 : oslSocketAddr SAL_CALL osl_psz_resolveHostname(const sal_Char* pszHostname)
1120 : {
1121 0 : struct oslHostAddrImpl *pAddr = (oslHostAddr)osl_psz_createHostAddrByName(pszHostname);
1122 :
1123 0 : if (pAddr)
1124 : {
1125 0 : oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr);
1126 :
1127 0 : osl_destroyHostAddr(pAddr);
1128 :
1129 0 : return (SockAddr);
1130 : }
1131 :
1132 0 : return ((oslSocketAddr)NULL);
1133 : }
1134 :
1135 0 : sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol)
1136 : {
1137 : sal_Int32 nPort;
1138 0 : rtl_String* strServicename=0;
1139 0 : rtl_String* strProtocol=0;
1140 0 : sal_Char* pszServiceName=0;
1141 0 : sal_Char* pszProtocol=0;
1142 :
1143 0 : if ( ustrServicename != 0 )
1144 : {
1145 0 : rtl_uString2String( &strServicename,
1146 0 : rtl_uString_getStr(ustrServicename),
1147 : rtl_uString_getLength(ustrServicename),
1148 : RTL_TEXTENCODING_UTF8,
1149 : OUSTRING_TO_OSTRING_CVTFLAGS );
1150 0 : pszServiceName = rtl_string_getStr(strServicename);
1151 : }
1152 :
1153 0 : if ( ustrProtocol != 0 )
1154 : {
1155 0 : rtl_uString2String( &strProtocol,
1156 0 : rtl_uString_getStr(ustrProtocol),
1157 : rtl_uString_getLength(ustrProtocol),
1158 : RTL_TEXTENCODING_UTF8,
1159 : OUSTRING_TO_OSTRING_CVTFLAGS );
1160 0 : pszProtocol = rtl_string_getStr(strProtocol);
1161 : }
1162 :
1163 0 : nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
1164 :
1165 0 : if ( strServicename != 0 )
1166 : {
1167 0 : rtl_string_release(strServicename);
1168 : }
1169 :
1170 0 : if ( strProtocol != 0 )
1171 : {
1172 0 : rtl_string_release(strProtocol);
1173 : }
1174 :
1175 0 : return nPort;
1176 : }
1177 :
1178 0 : sal_Int32 SAL_CALL osl_psz_getServicePort(const sal_Char* pszServicename,
1179 : const sal_Char* pszProtocol)
1180 : {
1181 : struct servent* ps;
1182 :
1183 0 : ps= getservbyname(pszServicename, pszProtocol);
1184 :
1185 0 : if (ps != 0)
1186 0 : return ntohs(ps->s_port);
1187 :
1188 0 : return OSL_INVALID_PORT;
1189 : }
1190 :
1191 0 : void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
1192 : {
1193 0 : __osl_destroySocketAddr( pAddr );
1194 0 : }
1195 :
1196 0 : oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
1197 : {
1198 : OSL_ASSERT(pAddr);
1199 :
1200 0 : if (pAddr)
1201 0 : return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
1202 : else
1203 0 : return osl_Socket_FamilyInvalid;
1204 : }
1205 :
1206 0 : sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
1207 : {
1208 : OSL_ASSERT(pAddr);
1209 0 : if( pAddr )
1210 : {
1211 0 : struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
1212 :
1213 0 : if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1214 0 : return ntohs(pSystemInetAddr->sin_port);
1215 : }
1216 0 : return OSL_INVALID_PORT;
1217 : }
1218 :
1219 0 : sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port)
1220 : {
1221 : OSL_ASSERT(pAddr);
1222 0 : if( pAddr )
1223 : {
1224 0 : struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
1225 0 : if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1226 : {
1227 0 : pSystemInetAddr->sin_port= htons((short)Port);
1228 0 : return sal_True;
1229 : }
1230 : }
1231 :
1232 : /* this is not a inet-addr => can't set port */
1233 0 : return sal_False;
1234 : }
1235 :
1236 0 : oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
1237 : {
1238 : oslSocketResult Result;
1239 : sal_Char pszHostname[1024];
1240 :
1241 0 : pszHostname[0] = '\0';
1242 :
1243 0 : Result = osl_psz_getHostnameOfSocketAddr(Addr,pszHostname,sizeof(pszHostname));
1244 :
1245 0 : rtl_uString_newFromAscii(ustrHostname,pszHostname);
1246 :
1247 0 : return Result;
1248 : }
1249 :
1250 0 : oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr,
1251 : sal_Char *pBuffer, sal_uInt32 BufferSize)
1252 : {
1253 0 : oslHostAddr pHostAddr= (oslHostAddr )osl_createHostAddrByAddr(pAddr);
1254 :
1255 0 : if (pHostAddr)
1256 : {
1257 0 : strncpy(pBuffer, pHostAddr->pHostName, BufferSize);
1258 0 : pBuffer[BufferSize - 1] = '\0';
1259 :
1260 0 : osl_destroyHostAddr(pHostAddr);
1261 :
1262 0 : return osl_Socket_Ok;
1263 : }
1264 :
1265 0 : return osl_Socket_Error;
1266 : }
1267 :
1268 : /*****************************************************************************/
1269 : /* osl_getDottedInetAddrOfSocketAddr */
1270 : /*****************************************************************************/
1271 0 : oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
1272 : {
1273 : oslSocketResult Result;
1274 : sal_Char pszDottedInetAddr[1024];
1275 :
1276 0 : pszDottedInetAddr[0] = '\0';
1277 :
1278 0 : Result = osl_psz_getDottedInetAddrOfSocketAddr(Addr,pszDottedInetAddr,sizeof(pszDottedInetAddr));
1279 :
1280 0 : rtl_uString_newFromAscii(ustrDottedInetAddr,pszDottedInetAddr);
1281 :
1282 0 : return Result;
1283 :
1284 : }
1285 :
1286 0 : oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr,
1287 : sal_Char *pBuffer, sal_uInt32 BufferSize)
1288 : {
1289 : OSL_ASSERT(pAddr);
1290 :
1291 0 : if( pAddr )
1292 : {
1293 0 : struct sockaddr_in* pSystemInetAddr = ( struct sockaddr_in * ) &(pAddr->m_sockaddr);
1294 :
1295 0 : if (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1296 : {
1297 0 : strncpy(pBuffer, inet_ntoa(pSystemInetAddr->sin_addr), BufferSize);
1298 0 : pBuffer[BufferSize - 1] = '\0';
1299 :
1300 0 : return osl_Socket_Ok;
1301 : }
1302 : }
1303 :
1304 0 : return osl_Socket_Error;
1305 : }
1306 :
1307 0 : oslSocket SAL_CALL osl_createSocket(oslAddrFamily Family,
1308 : oslSocketType Type,
1309 : oslProtocol Protocol)
1310 : {
1311 : int Flags;
1312 : oslSocket pSocket;
1313 :
1314 : /* alloc memory */
1315 0 : pSocket= __osl_createSocketImpl(OSL_INVALID_SOCKET);
1316 :
1317 : /* create socket */
1318 0 : pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
1319 0 : TYPE_TO_NATIVE(Type),
1320 0 : PROTOCOL_TO_NATIVE(Protocol));
1321 :
1322 : /* creation failed => free memory */
1323 0 : if(pSocket->m_Socket == OSL_INVALID_SOCKET)
1324 : {
1325 : OSL_TRACE("osl_createSocket failed. Errno: %d; %s\n",
1326 : errno,
1327 : strerror(errno));
1328 :
1329 0 : __osl_destroySocketImpl((pSocket));
1330 0 : pSocket= 0;
1331 : }
1332 : else
1333 : {
1334 : /* set close-on-exec flag */
1335 0 : if ((Flags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
1336 : {
1337 0 : Flags |= FD_CLOEXEC;
1338 0 : if (fcntl(pSocket->m_Socket, F_SETFD, Flags) == -1)
1339 : {
1340 0 : pSocket->m_nLastError=errno;
1341 : OSL_TRACE("osl_createSocket failed changing socket flags. Errno: %d; %s\n",
1342 : errno,
1343 : strerror(errno));
1344 : }
1345 : }
1346 : else
1347 : {
1348 0 : pSocket->m_nLastError=errno;
1349 : }
1350 : }
1351 :
1352 0 : return pSocket;
1353 : }
1354 :
1355 0 : void SAL_CALL osl_acquireSocket(oslSocket pSocket)
1356 : {
1357 0 : osl_atomic_increment( &(pSocket->m_nRefCount ) );
1358 0 : }
1359 :
1360 0 : void SAL_CALL osl_releaseSocket( oslSocket pSocket )
1361 : {
1362 0 : if( pSocket && 0 == osl_atomic_decrement( &(pSocket->m_nRefCount) ) )
1363 : {
1364 : #if defined(LINUX)
1365 0 : if ( pSocket->m_bIsAccepting == sal_True )
1366 : {
1367 : OSL_FAIL("osl_destroySocket : attempt to destroy socket while accepting\n");
1368 0 : return;
1369 : }
1370 : #endif /* LINUX */
1371 0 : osl_closeSocket( pSocket );
1372 0 : __osl_destroySocketImpl( pSocket );
1373 : }
1374 : }
1375 :
1376 0 : void SAL_CALL osl_closeSocket(oslSocket pSocket)
1377 : {
1378 : int nRet;
1379 : int nFD;
1380 :
1381 : /* socket already invalid */
1382 0 : if(pSocket==0)
1383 0 : return;
1384 :
1385 0 : pSocket->m_nLastError=0;
1386 0 : nFD = pSocket->m_Socket;
1387 :
1388 0 : if (nFD == OSL_INVALID_SOCKET)
1389 0 : return;
1390 :
1391 0 : pSocket->m_Socket = OSL_INVALID_SOCKET;
1392 :
1393 : #if defined(LINUX)
1394 0 : pSocket->m_bIsInShutdown = sal_True;
1395 :
1396 0 : if ( pSocket->m_bIsAccepting == sal_True )
1397 : {
1398 : int nConnFD;
1399 : union {
1400 : struct sockaddr aSockAddr;
1401 : struct sockaddr_in aSockAddrIn;
1402 : } s;
1403 0 : socklen_t nSockLen = sizeof(s.aSockAddr);
1404 :
1405 0 : nRet = getsockname(nFD, &s.aSockAddr, &nSockLen);
1406 : if ( nRet < 0 )
1407 : {
1408 : OSL_TRACE("getsockname call failed with error: %s", strerror(errno));
1409 : }
1410 :
1411 0 : if ( s.aSockAddr.sa_family == AF_INET )
1412 : {
1413 0 : if ( s.aSockAddrIn.sin_addr.s_addr == htonl(INADDR_ANY) )
1414 : {
1415 0 : s.aSockAddrIn.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1416 : }
1417 :
1418 0 : nConnFD = socket(AF_INET, SOCK_STREAM, 0);
1419 0 : if ( nConnFD < 0 )
1420 : {
1421 : OSL_TRACE("socket call failed with error: %s", strerror(errno));
1422 : }
1423 : else
1424 : {
1425 0 : nRet = connect(nConnFD, &s.aSockAddr, sizeof(s.aSockAddr));
1426 : if ( nRet < 0 )
1427 : {
1428 : OSL_TRACE("connect call failed with error: %s", strerror(errno));
1429 : }
1430 0 : close(nConnFD);
1431 : }
1432 : }
1433 0 : pSocket->m_bIsAccepting = sal_False;
1434 : }
1435 : #endif /* LINUX */
1436 :
1437 0 : nRet=close(nFD);
1438 0 : if ( nRet != 0 )
1439 : {
1440 0 : pSocket->m_nLastError=errno;
1441 : OSL_TRACE("closeSocket close error '%s'",strerror(errno));
1442 : }
1443 :
1444 0 : pSocket->m_Socket = OSL_INVALID_SOCKET;
1445 : }
1446 :
1447 : /*****************************************************************************/
1448 : /* osl_getLocalAddrOfSocket */
1449 : /* Note that I rely on the fact that oslSocketAddr and struct sockaddr */
1450 : /* are the same! I don't like it very much but see no other easy way to conceal */
1451 : /* the struct sockaddr from the eyes of the user. */
1452 : /*****************************************************************************/
1453 0 : oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
1454 : {
1455 : socklen_t AddrLen;
1456 : struct sockaddr Addr;
1457 : oslSocketAddr pAddr;
1458 :
1459 0 : if (pSocket == NULL) /* ENOTSOCK */
1460 0 : return ((oslSocketAddr)NULL);
1461 :
1462 0 : AddrLen= sizeof(struct sockaddr);
1463 :
1464 0 : if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1465 0 : return ((oslSocketAddr)NULL);
1466 :
1467 0 : pAddr = __osl_createSocketAddrFromSystem( &Addr );
1468 0 : return pAddr;
1469 : }
1470 :
1471 0 : oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
1472 : {
1473 : socklen_t AddrLen;
1474 : struct sockaddr Addr;
1475 :
1476 : OSL_ASSERT(pSocket);
1477 0 : if ( pSocket == 0 )
1478 : {
1479 0 : return 0;
1480 : }
1481 :
1482 0 : pSocket->m_nLastError=0;
1483 0 : AddrLen= sizeof(struct sockaddr);
1484 :
1485 0 : if(getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1486 : {
1487 0 : pSocket->m_nLastError=errno;
1488 0 : return 0;
1489 : }
1490 0 : return __osl_createSocketAddrFromSystem( &Addr );
1491 : }
1492 :
1493 0 : sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
1494 : oslSocketAddr pAddr)
1495 : {
1496 : int nRet;
1497 :
1498 : OSL_ASSERT(pSocket && pAddr );
1499 0 : if ( pSocket == 0 || pAddr == 0 )
1500 : {
1501 0 : return sal_False;
1502 : }
1503 :
1504 0 : pSocket->m_nLastError=0;
1505 :
1506 0 : nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
1507 :
1508 0 : if ( nRet == OSL_SOCKET_ERROR)
1509 : {
1510 0 : pSocket->m_nLastError=errno;
1511 0 : return sal_False;
1512 : }
1513 :
1514 0 : return sal_True;
1515 : }
1516 :
1517 0 : sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
1518 : sal_Int32 MaxPendingConnections)
1519 : {
1520 : int nRet;
1521 :
1522 : OSL_ASSERT(pSocket);
1523 0 : if ( pSocket == 0 )
1524 : {
1525 0 : return sal_False;
1526 : }
1527 :
1528 0 : pSocket->m_nLastError=0;
1529 :
1530 0 : nRet = listen(pSocket->m_Socket,
1531 : MaxPendingConnections == -1 ?
1532 : SOMAXCONN :
1533 : MaxPendingConnections);
1534 0 : if ( nRet == OSL_SOCKET_ERROR)
1535 : {
1536 0 : pSocket->m_nLastError=errno;
1537 0 : return sal_False;
1538 : }
1539 :
1540 0 : return sal_True;
1541 : }
1542 :
1543 0 : oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
1544 : oslSocketAddr pAddr,
1545 : const TimeValue* pTimeout)
1546 : {
1547 : fd_set WriteSet;
1548 : fd_set ExcptSet;
1549 : int ReadyHandles;
1550 : struct timeval tv;
1551 0 : oslSocketResult Result= osl_Socket_Ok;
1552 :
1553 : OSL_PRECOND(pSocket, "osl_connectSocketTo(): need a valid socket!\n");
1554 :
1555 0 : if ( pSocket == 0 )
1556 : {
1557 0 : return osl_Socket_Error;
1558 : }
1559 :
1560 0 : pSocket->m_nLastError=0;
1561 :
1562 0 : if (osl_isNonBlockingMode(pSocket))
1563 : {
1564 0 : if (connect(pSocket->m_Socket,
1565 0 : &(pAddr->m_sockaddr),
1566 : sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1567 0 : return osl_Socket_Ok;
1568 : else
1569 0 : if (errno == EWOULDBLOCK || errno == EINPROGRESS)
1570 : {
1571 0 : pSocket->m_nLastError=EINPROGRESS;
1572 0 : return osl_Socket_InProgress;
1573 : }
1574 :
1575 0 : pSocket->m_nLastError=errno;
1576 : OSL_TRACE("can't connect : '%s'",strerror(errno));
1577 0 : return osl_Socket_Error;
1578 : }
1579 :
1580 : /* set socket temporarily to non-blocking */
1581 0 : OSL_VERIFY(osl_enableNonBlockingMode(pSocket, sal_True));
1582 :
1583 : /* initiate connect */
1584 0 : if(connect(pSocket->m_Socket,
1585 0 : &(pAddr->m_sockaddr),
1586 : sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1587 : {
1588 : /* immediate connection */
1589 0 : osl_enableNonBlockingMode(pSocket, sal_False);
1590 :
1591 0 : return osl_Socket_Ok;
1592 : }
1593 : else
1594 : {
1595 : /* really an error or just delayed? */
1596 0 : if (errno != EINPROGRESS)
1597 : {
1598 0 : pSocket->m_nLastError=errno;
1599 : OSL_TRACE(
1600 : "osl_connectSocketTo(): connect failed: errno: %d (%s)\n",
1601 : errno, strerror(errno));
1602 :
1603 0 : osl_enableNonBlockingMode(pSocket, sal_False);
1604 0 : return osl_Socket_Error;
1605 : }
1606 : }
1607 :
1608 : /* prepare select set for socket */
1609 0 : FD_ZERO(&WriteSet);
1610 0 : FD_ZERO(&ExcptSet);
1611 0 : FD_SET(pSocket->m_Socket, &WriteSet);
1612 0 : FD_SET(pSocket->m_Socket, &ExcptSet);
1613 :
1614 : /* prepare timeout */
1615 0 : if (pTimeout)
1616 : {
1617 : /* divide milliseconds into seconds and microseconds */
1618 0 : tv.tv_sec= pTimeout->Seconds;
1619 0 : tv.tv_usec= pTimeout->Nanosec / 1000L;
1620 : }
1621 :
1622 : /* select */
1623 0 : ReadyHandles= select(pSocket->m_Socket+1,
1624 : 0,
1625 : PTR_FD_SET(WriteSet),
1626 : PTR_FD_SET(ExcptSet),
1627 : (pTimeout) ? &tv : 0);
1628 :
1629 0 : if (ReadyHandles > 0) /* connected */
1630 : {
1631 0 : if ( FD_ISSET(pSocket->m_Socket, &WriteSet ) )
1632 : {
1633 0 : int nErrorCode = 0;
1634 0 : socklen_t nErrorSize = sizeof( nErrorCode );
1635 :
1636 : int nSockOpt;
1637 :
1638 0 : nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
1639 : &nErrorCode, &nErrorSize );
1640 0 : if ( (nSockOpt == 0) && (nErrorCode == 0))
1641 0 : Result = osl_Socket_Ok;
1642 : else
1643 0 : Result = osl_Socket_Error;
1644 : }
1645 : else
1646 : {
1647 0 : Result= osl_Socket_Error;
1648 : }
1649 : }
1650 0 : else if (ReadyHandles < 0) /* error */
1651 : {
1652 0 : if (errno == EBADF) /* most probably interrupted by close() */
1653 : {
1654 : /* do not access pSockImpl because it is about to be or */
1655 : /* already destroyed */
1656 0 : return osl_Socket_Interrupted;
1657 : }
1658 : else
1659 : {
1660 0 : pSocket->m_nLastError=errno;
1661 0 : Result= osl_Socket_Error;
1662 : }
1663 : }
1664 : else /* timeout */
1665 : {
1666 0 : pSocket->m_nLastError=errno;
1667 0 : Result= osl_Socket_TimedOut;
1668 : }
1669 :
1670 0 : osl_enableNonBlockingMode(pSocket, sal_False);
1671 :
1672 0 : return Result;
1673 : }
1674 :
1675 0 : oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
1676 : oslSocketAddr* ppAddr)
1677 : {
1678 : struct sockaddr Addr;
1679 : int Connection, Flags;
1680 : oslSocket pConnectionSockImpl;
1681 :
1682 0 : socklen_t AddrLen = sizeof(struct sockaddr);
1683 : OSL_ASSERT(pSocket);
1684 0 : if ( pSocket == 0 )
1685 : {
1686 0 : return 0;
1687 : }
1688 :
1689 0 : pSocket->m_nLastError=0;
1690 : #if defined(LINUX)
1691 0 : pSocket->m_bIsAccepting = sal_True;
1692 : #endif /* LINUX */
1693 :
1694 0 : if( ppAddr && *ppAddr )
1695 : {
1696 0 : osl_destroySocketAddr( *ppAddr );
1697 0 : *ppAddr = 0;
1698 : }
1699 :
1700 : /* prevent Linux EINTR behaviour */
1701 : do
1702 : {
1703 0 : Connection = accept(pSocket->m_Socket, &Addr, &AddrLen);
1704 0 : } while (Connection == -1 && errno == EINTR);
1705 :
1706 : /* accept failed? */
1707 0 : if( Connection == OSL_SOCKET_ERROR )
1708 : {
1709 0 : pSocket->m_nLastError=errno;
1710 : OSL_TRACE("osl_acceptConnectionOnSocket : accept error '%s'",strerror(errno));
1711 :
1712 : #if defined(LINUX)
1713 0 : pSocket->m_bIsAccepting = sal_False;
1714 : #endif /* LINUX */
1715 0 : return 0;
1716 : }
1717 :
1718 : OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
1719 :
1720 : #if defined(LINUX)
1721 0 : if ( pSocket->m_bIsInShutdown == sal_True )
1722 : {
1723 0 : close(Connection);
1724 : OSL_TRACE("osl_acceptConnectionOnSocket : close while accept");
1725 0 : return 0;
1726 : }
1727 : #endif /* LINUX */
1728 :
1729 0 : if(ppAddr)
1730 : {
1731 0 : *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
1732 : }
1733 :
1734 : /* alloc memory */
1735 0 : pConnectionSockImpl= __osl_createSocketImpl(OSL_INVALID_SOCKET);
1736 :
1737 : /* set close-on-exec flag */
1738 0 : if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
1739 : {
1740 0 : Flags |= FD_CLOEXEC;
1741 0 : if (fcntl(Connection, F_SETFD, Flags) == -1)
1742 : {
1743 0 : pSocket->m_nLastError=errno;
1744 : OSL_TRACE("osl_acceptConnectionOnSocket failed changing socket flags. Errno: %d (%s)\n",
1745 : errno,
1746 : strerror(errno));
1747 : }
1748 :
1749 : }
1750 :
1751 0 : pConnectionSockImpl->m_Socket = Connection;
1752 0 : pConnectionSockImpl->m_nLastError = 0;
1753 : #if defined(LINUX)
1754 0 : pConnectionSockImpl->m_bIsAccepting = sal_False;
1755 :
1756 0 : pSocket->m_bIsAccepting = sal_False;
1757 : #endif /* LINUX */
1758 0 : return pConnectionSockImpl;
1759 : }
1760 :
1761 0 : sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
1762 : void* pBuffer,
1763 : sal_uInt32 BytesToRead,
1764 : oslSocketMsgFlag Flag)
1765 : {
1766 : int nRead;
1767 :
1768 : OSL_ASSERT(pSocket);
1769 0 : if ( pSocket == 0 )
1770 : {
1771 : OSL_TRACE("osl_receiveSocket : Invalid socket");
1772 0 : return -1;
1773 : }
1774 :
1775 0 : pSocket->m_nLastError=0;
1776 :
1777 : do
1778 : {
1779 0 : nRead = recv(pSocket->m_Socket,
1780 : (sal_Char*)pBuffer,
1781 : BytesToRead,
1782 0 : MSG_FLAG_TO_NATIVE(Flag));
1783 0 : } while ( nRead < 0 && errno == EINTR );
1784 :
1785 0 : if ( nRead < 0 )
1786 : {
1787 0 : pSocket->m_nLastError=errno;
1788 : OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,strerror(errno));
1789 : }
1790 : else if ( nRead == 0 )
1791 : {
1792 : OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
1793 : }
1794 :
1795 0 : return nRead;
1796 : }
1797 :
1798 0 : sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
1799 : oslSocketAddr pSenderAddr,
1800 : void* pBuffer,
1801 : sal_uInt32 BufferSize,
1802 : oslSocketMsgFlag Flag)
1803 : {
1804 : int nRead;
1805 0 : struct sockaddr *pSystemSockAddr = 0;
1806 0 : socklen_t AddrLen = 0;
1807 0 : if( pSenderAddr )
1808 : {
1809 0 : AddrLen = sizeof( struct sockaddr );
1810 0 : pSystemSockAddr = &(pSenderAddr->m_sockaddr);
1811 : }
1812 :
1813 : OSL_ASSERT(pSocket);
1814 0 : if ( pSocket == 0 )
1815 : {
1816 : OSL_TRACE("osl_receiveFromSocket : Invalid socket");
1817 0 : return -1;
1818 : }
1819 :
1820 0 : pSocket->m_nLastError=0;
1821 :
1822 0 : nRead = recvfrom(pSocket->m_Socket,
1823 : (sal_Char*)pBuffer,
1824 : BufferSize,
1825 0 : MSG_FLAG_TO_NATIVE(Flag),
1826 : pSystemSockAddr,
1827 : &AddrLen);
1828 :
1829 0 : if ( nRead < 0 )
1830 : {
1831 0 : pSocket->m_nLastError=errno;
1832 : OSL_TRACE("osl_receiveFromSocket failed : %i '%s'",nRead,strerror(errno));
1833 : }
1834 : else if ( nRead == 0 )
1835 : {
1836 : OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
1837 : }
1838 :
1839 0 : return nRead;
1840 : }
1841 :
1842 0 : sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
1843 : const void* pBuffer,
1844 : sal_uInt32 BytesToSend,
1845 : oslSocketMsgFlag Flag)
1846 : {
1847 : int nWritten;
1848 :
1849 : OSL_ASSERT(pSocket);
1850 0 : if ( pSocket == 0 )
1851 : {
1852 : OSL_TRACE("osl_sendSocket : Invalid socket");
1853 0 : return -1;
1854 : }
1855 :
1856 0 : pSocket->m_nLastError=0;
1857 :
1858 : do
1859 : {
1860 0 : nWritten = send(pSocket->m_Socket,
1861 : (sal_Char*)pBuffer,
1862 : BytesToSend,
1863 0 : MSG_FLAG_TO_NATIVE(Flag));
1864 0 : } while ( nWritten < 0 && errno == EINTR );
1865 :
1866 0 : if ( nWritten < 0 )
1867 : {
1868 0 : pSocket->m_nLastError=errno;
1869 : OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,strerror(errno));
1870 : }
1871 : else if ( nWritten == 0 )
1872 : {
1873 : OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,"EOL");
1874 : }
1875 :
1876 0 : return nWritten;
1877 : }
1878 :
1879 0 : sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
1880 : oslSocketAddr ReceiverAddr,
1881 : const void* pBuffer,
1882 : sal_uInt32 BytesToSend,
1883 : oslSocketMsgFlag Flag)
1884 : {
1885 : int nWritten;
1886 :
1887 0 : struct sockaddr *pSystemSockAddr = 0;
1888 0 : int AddrLen = 0;
1889 0 : if( ReceiverAddr )
1890 : {
1891 0 : pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
1892 0 : AddrLen = sizeof( struct sockaddr );
1893 : }
1894 :
1895 : OSL_ASSERT(pSocket);
1896 0 : if ( pSocket == 0 )
1897 : {
1898 : OSL_TRACE("osl_sendToSocket : Invalid socket");
1899 0 : return -1;
1900 : }
1901 :
1902 0 : pSocket->m_nLastError=0;
1903 :
1904 : /* ReceiverAddr might be 0 when used on a connected socket. */
1905 : /* Then sendto should behave like send. */
1906 :
1907 0 : nWritten = sendto(pSocket->m_Socket,
1908 : (sal_Char*)pBuffer,
1909 : BytesToSend,
1910 0 : MSG_FLAG_TO_NATIVE(Flag),
1911 : pSystemSockAddr,
1912 : AddrLen);
1913 :
1914 0 : if ( nWritten < 0 )
1915 : {
1916 0 : pSocket->m_nLastError=errno;
1917 : OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,strerror(errno));
1918 : }
1919 : else if ( nWritten == 0 )
1920 : {
1921 : OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,"EOL");
1922 : }
1923 :
1924 0 : return nWritten;
1925 : }
1926 :
1927 0 : sal_Int32 SAL_CALL osl_readSocket (
1928 : oslSocket pSocket, void *pBuffer, sal_Int32 n )
1929 : {
1930 0 : sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
1931 0 : sal_uInt32 BytesRead= 0;
1932 0 : sal_uInt32 BytesToRead= n;
1933 :
1934 : OSL_ASSERT( pSocket);
1935 :
1936 : /* loop until all desired bytes were read or an error occurred */
1937 0 : while (BytesToRead > 0)
1938 : {
1939 : sal_Int32 RetVal;
1940 0 : RetVal= osl_receiveSocket(pSocket,
1941 : Ptr,
1942 : BytesToRead,
1943 : osl_Socket_MsgNormal);
1944 :
1945 : /* error occurred? */
1946 0 : if(RetVal <= 0)
1947 : {
1948 0 : break;
1949 : }
1950 :
1951 0 : BytesToRead -= RetVal;
1952 0 : BytesRead += RetVal;
1953 0 : Ptr += RetVal;
1954 : }
1955 :
1956 0 : return BytesRead;
1957 : }
1958 :
1959 0 : sal_Int32 SAL_CALL osl_writeSocket(
1960 : oslSocket pSocket, const void *pBuffer, sal_Int32 n )
1961 : {
1962 : /* loop until all desired bytes were send or an error occurred */
1963 0 : sal_uInt32 BytesSend= 0;
1964 0 : sal_uInt32 BytesToSend= n;
1965 0 : sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer;
1966 :
1967 : OSL_ASSERT( pSocket );
1968 :
1969 0 : while (BytesToSend > 0)
1970 : {
1971 : sal_Int32 RetVal;
1972 :
1973 0 : RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
1974 :
1975 : /* error occurred? */
1976 0 : if(RetVal <= 0)
1977 : {
1978 0 : break;
1979 : }
1980 :
1981 0 : BytesToSend -= RetVal;
1982 0 : BytesSend += RetVal;
1983 0 : Ptr += RetVal;
1984 :
1985 : }
1986 0 : return BytesSend;
1987 : }
1988 :
1989 : #ifdef HAVE_POLL_H /* poll() */
1990 :
1991 0 : sal_Bool __osl_socket_poll (
1992 : oslSocket pSocket,
1993 : const TimeValue* pTimeout,
1994 : short nEvent)
1995 : {
1996 : struct pollfd fds;
1997 : int timeout;
1998 : int result;
1999 :
2000 : OSL_ASSERT(0 != pSocket);
2001 0 : if (0 == pSocket)
2002 0 : return sal_False; /* EINVAL */
2003 :
2004 0 : pSocket->m_nLastError = 0;
2005 :
2006 0 : fds.fd = pSocket->m_Socket;
2007 0 : fds.events = nEvent;
2008 0 : fds.revents = 0;
2009 :
2010 0 : timeout = -1;
2011 0 : if (pTimeout)
2012 : {
2013 : /* Convert to [ms] */
2014 0 : timeout = pTimeout->Seconds * 1000;
2015 0 : timeout += pTimeout->Nanosec / (1000 * 1000);
2016 : }
2017 :
2018 0 : result = poll (&fds, 1, timeout);
2019 0 : if (result < 0)
2020 : {
2021 0 : pSocket->m_nLastError = errno;
2022 : OSL_TRACE("__osl_socket_poll(): poll error: %d (%s)",
2023 : errno, strerror(errno));
2024 0 : return sal_False;
2025 : }
2026 0 : if (result == 0)
2027 : {
2028 : /* Timeout */
2029 0 : return sal_False;
2030 : }
2031 :
2032 0 : return ((fds.revents & nEvent) == nEvent);
2033 : }
2034 :
2035 : #else /* select() */
2036 :
2037 : sal_Bool __osl_socket_poll (
2038 : oslSocket pSocket,
2039 : const TimeValue* pTimeout,
2040 : short nEvent)
2041 : {
2042 : fd_set fds;
2043 : struct timeval tv;
2044 : int result;
2045 :
2046 : OSL_ASSERT(0 != pSocket);
2047 : if (0 == pSocket)
2048 : return sal_False; /* EINVAL */
2049 :
2050 : pSocket->m_nLastError = 0;
2051 :
2052 : FD_ZERO(&fds);
2053 : FD_SET(pSocket->m_Socket, &fds);
2054 :
2055 : if (pTimeout)
2056 : {
2057 : /* Convert to 'timeval' */
2058 : tv.tv_sec = pTimeout->Seconds;
2059 : tv.tv_usec = pTimeout->Nanosec / 1000;
2060 : }
2061 :
2062 : result = select (
2063 : pSocket->m_Socket + 1,
2064 : (nEvent == POLLIN ) ? PTR_FD_SET(fds) : NULL,
2065 : (nEvent == POLLOUT) ? PTR_FD_SET(fds) : NULL,
2066 : (nEvent == POLLPRI) ? PTR_FD_SET(fds) : NULL,
2067 : (pTimeout) ? &tv : NULL);
2068 :
2069 : if (result < 0)
2070 : {
2071 : pSocket->m_nLastError = errno;
2072 : OSL_TRACE("__osl_socket_poll(): select error: %d (%s)",
2073 : errno, strerror(errno));
2074 : return sal_False;
2075 : }
2076 : if (result == 0)
2077 : {
2078 : /* Timeout */
2079 : return sal_False;
2080 : }
2081 :
2082 : return (FD_ISSET(pSocket->m_Socket, &fds) ? sal_True : sal_False);
2083 : }
2084 :
2085 : #endif /* HAVE_POLL_H */
2086 :
2087 0 : sal_Bool SAL_CALL osl_isReceiveReady (
2088 : oslSocket pSocket, const TimeValue* pTimeout)
2089 : {
2090 : OSL_ASSERT(pSocket);
2091 0 : if (pSocket == NULL)
2092 : {
2093 : /* ENOTSOCK */
2094 0 : return sal_False;
2095 : }
2096 :
2097 0 : return __osl_socket_poll (pSocket, pTimeout, POLLIN);
2098 : }
2099 :
2100 0 : sal_Bool SAL_CALL osl_isSendReady (
2101 : oslSocket pSocket, const TimeValue* pTimeout)
2102 : {
2103 : OSL_ASSERT(pSocket);
2104 0 : if (pSocket == NULL)
2105 : {
2106 : /* ENOTSOCK */
2107 0 : return sal_False;
2108 : }
2109 :
2110 0 : return __osl_socket_poll (pSocket, pTimeout, POLLOUT);
2111 : }
2112 :
2113 0 : sal_Bool SAL_CALL osl_isExceptionPending (
2114 : oslSocket pSocket, const TimeValue* pTimeout)
2115 : {
2116 : OSL_ASSERT(pSocket);
2117 0 : if (pSocket == NULL)
2118 : {
2119 : /* ENOTSOCK */
2120 0 : return sal_False;
2121 : }
2122 :
2123 0 : return __osl_socket_poll (pSocket, pTimeout, POLLPRI);
2124 : }
2125 :
2126 0 : sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
2127 : oslSocketDirection Direction)
2128 : {
2129 : int nRet;
2130 :
2131 : OSL_ASSERT(pSocket);
2132 0 : if ( pSocket == 0 )
2133 : {
2134 0 : return sal_False;
2135 : }
2136 :
2137 0 : pSocket->m_nLastError=0;
2138 :
2139 0 : nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
2140 0 : if (nRet != 0 )
2141 : {
2142 0 : pSocket->m_nLastError=errno;
2143 : OSL_TRACE("shutdown error '%s'",strerror(errno));
2144 : }
2145 0 : return (nRet==0);
2146 : }
2147 :
2148 0 : sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
2149 : oslSocketOptionLevel Level,
2150 : oslSocketOption Option,
2151 : void* pBuffer,
2152 : sal_uInt32 BufferLen)
2153 : {
2154 0 : socklen_t nOptLen = (socklen_t) BufferLen;
2155 :
2156 : OSL_ASSERT(pSocket);
2157 0 : if ( pSocket == 0 )
2158 : {
2159 0 : return -1;
2160 : }
2161 :
2162 0 : pSocket->m_nLastError=0;
2163 :
2164 0 : if(getsockopt(pSocket->m_Socket,
2165 0 : OPTION_LEVEL_TO_NATIVE(Level),
2166 0 : OPTION_TO_NATIVE(Option),
2167 : (sal_Char*)pBuffer,
2168 : &nOptLen) == -1)
2169 : {
2170 0 : pSocket->m_nLastError=errno;
2171 0 : return -1;
2172 : }
2173 :
2174 0 : return BufferLen;
2175 : }
2176 :
2177 0 : sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
2178 : oslSocketOptionLevel Level,
2179 : oslSocketOption Option,
2180 : void* pBuffer,
2181 : sal_uInt32 BufferLen)
2182 : {
2183 : int nRet;
2184 :
2185 : OSL_ASSERT(pSocket);
2186 0 : if ( pSocket == 0 )
2187 : {
2188 0 : return sal_False;
2189 : }
2190 :
2191 0 : pSocket->m_nLastError=0;
2192 :
2193 0 : nRet = setsockopt(pSocket->m_Socket,
2194 0 : OPTION_LEVEL_TO_NATIVE(Level),
2195 0 : OPTION_TO_NATIVE(Option),
2196 : (sal_Char*)pBuffer,
2197 : BufferLen);
2198 :
2199 0 : if ( nRet < 0 )
2200 : {
2201 0 : pSocket->m_nLastError=errno;
2202 0 : return sal_False;
2203 : }
2204 :
2205 0 : return sal_True;
2206 : }
2207 :
2208 0 : sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
2209 : sal_Bool On)
2210 : {
2211 : int flags;
2212 : int nRet;
2213 :
2214 : OSL_ASSERT(pSocket);
2215 0 : if ( pSocket == 0 )
2216 : {
2217 0 : return sal_False;
2218 : }
2219 :
2220 0 : pSocket->m_nLastError=0;
2221 :
2222 0 : flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
2223 :
2224 0 : if (On)
2225 0 : flags |= O_NONBLOCK;
2226 : else
2227 0 : flags &= ~(O_NONBLOCK);
2228 :
2229 0 : nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
2230 :
2231 0 : if ( nRet < 0 )
2232 : {
2233 0 : pSocket->m_nLastError=errno;
2234 0 : return sal_False;
2235 : }
2236 :
2237 0 : return sal_True;
2238 : }
2239 :
2240 0 : sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
2241 : {
2242 : int flags;
2243 :
2244 : OSL_ASSERT(pSocket);
2245 0 : if ( pSocket == 0 )
2246 : {
2247 0 : return sal_False;
2248 : }
2249 :
2250 0 : pSocket->m_nLastError=0;
2251 :
2252 0 : flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
2253 :
2254 0 : if (flags == -1 || !(flags & O_NONBLOCK))
2255 0 : return sal_False;
2256 : else
2257 0 : return sal_True;
2258 : }
2259 :
2260 0 : oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
2261 : {
2262 0 : int Type=0;
2263 0 : socklen_t TypeSize= sizeof(Type);
2264 :
2265 : OSL_ASSERT(pSocket);
2266 0 : if ( pSocket == 0 )
2267 : {
2268 0 : return osl_Socket_TypeInvalid;
2269 : }
2270 :
2271 0 : pSocket->m_nLastError=0;
2272 :
2273 0 : if(getsockopt(pSocket->m_Socket,
2274 0 : OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
2275 0 : OPTION_TO_NATIVE(osl_Socket_OptionType),
2276 : (sal_Char*)&Type,
2277 : &TypeSize) == -1)
2278 : {
2279 : /* error */
2280 0 : pSocket->m_nLastError=errno;
2281 0 : return osl_Socket_TypeInvalid;
2282 : }
2283 :
2284 0 : return TYPE_FROM_NATIVE(Type);
2285 :
2286 : }
2287 :
2288 0 : void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
2289 : {
2290 : sal_Char pszError[1024];
2291 :
2292 0 : pszError[0] = '\0';
2293 :
2294 0 : osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
2295 :
2296 0 : rtl_uString_newFromAscii(ustrError,pszError);
2297 :
2298 0 : return;
2299 : }
2300 :
2301 0 : void SAL_CALL osl_psz_getLastSocketErrorDescription(oslSocket pSocket, sal_Char* pBuffer, sal_uInt32 BufferSize)
2302 : {
2303 : /* make sure pBuffer will be a zero-terminated string even when strncpy has to cut */
2304 0 : pBuffer[BufferSize-1]= '\0';
2305 :
2306 0 : if ( pSocket == 0 )
2307 : {
2308 0 : strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
2309 0 : return;
2310 : }
2311 :
2312 0 : strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
2313 0 : return;
2314 : }
2315 :
2316 0 : oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
2317 : {
2318 0 : if ( pSocket == 0 )
2319 : {
2320 0 : return ERROR_FROM_NATIVE(EINVAL);
2321 : }
2322 :
2323 0 : return ERROR_FROM_NATIVE(pSocket->m_nLastError);
2324 : }
2325 :
2326 : typedef struct _TSocketSetImpl
2327 : {
2328 : int m_MaxHandle; /* for select(), the largest descriptor in the set */
2329 : fd_set m_Set; /* the set of descriptors */
2330 :
2331 : } TSocketSetImpl;
2332 :
2333 0 : oslSocketSet SAL_CALL osl_createSocketSet()
2334 : {
2335 : TSocketSetImpl* pSet;
2336 :
2337 0 : pSet= (TSocketSetImpl*)malloc(sizeof(TSocketSetImpl));
2338 :
2339 : OSL_ASSERT(pSet);
2340 :
2341 0 : if(pSet)
2342 : {
2343 0 : pSet->m_MaxHandle= 0;
2344 0 : FD_ZERO(&pSet->m_Set);
2345 : }
2346 :
2347 0 : return (oslSocketSet)pSet;
2348 : }
2349 :
2350 0 : void SAL_CALL osl_destroySocketSet(oslSocketSet Set)
2351 : {
2352 0 : if(Set)
2353 0 : free(Set);
2354 0 : }
2355 :
2356 0 : void SAL_CALL osl_clearSocketSet(oslSocketSet Set)
2357 : {
2358 : TSocketSetImpl* pSet;
2359 : OSL_ASSERT(Set);
2360 0 : if ( Set == 0 )
2361 : {
2362 0 : return;
2363 : }
2364 :
2365 0 : pSet= (TSocketSetImpl*)Set;
2366 0 : pSet->m_MaxHandle= 0;
2367 :
2368 0 : FD_ZERO(&pSet->m_Set);
2369 : }
2370 :
2371 0 : void SAL_CALL osl_addToSocketSet(oslSocketSet Set, oslSocket pSocket)
2372 : {
2373 : TSocketSetImpl* pSet;
2374 :
2375 : OSL_ASSERT(Set);
2376 : OSL_ASSERT(pSocket);
2377 :
2378 0 : if ( Set == 0 || pSocket == 0)
2379 : {
2380 0 : return;
2381 : }
2382 :
2383 0 : pSet= (TSocketSetImpl*)Set;
2384 :
2385 : /* correct max handle */
2386 0 : if(pSocket->m_Socket > pSet->m_MaxHandle)
2387 0 : pSet->m_MaxHandle= pSocket->m_Socket;
2388 0 : FD_SET(pSocket->m_Socket, &pSet->m_Set);
2389 :
2390 : }
2391 :
2392 0 : void SAL_CALL osl_removeFromSocketSet(oslSocketSet Set, oslSocket pSocket)
2393 : {
2394 : TSocketSetImpl* pSet;
2395 :
2396 : OSL_ASSERT(Set);
2397 : OSL_ASSERT(pSocket);
2398 :
2399 0 : if ( Set == 0 || pSocket == 0)
2400 : {
2401 0 : return;
2402 : }
2403 :
2404 0 : pSet= (TSocketSetImpl*)Set;
2405 :
2406 : /* correct max handle */
2407 0 : if(pSocket->m_Socket == pSet->m_MaxHandle)
2408 : {
2409 : /* not optimal, since the next used descriptor might be */
2410 : /* much smaller than m_Socket-1, but it will do */
2411 0 : pSet->m_MaxHandle--;
2412 0 : if(pSet->m_MaxHandle < 0)
2413 : {
2414 0 : pSet->m_MaxHandle= 0; /* avoid underflow */
2415 : }
2416 : }
2417 :
2418 0 : FD_CLR(pSocket->m_Socket, &pSet->m_Set);
2419 : }
2420 :
2421 0 : sal_Bool SAL_CALL osl_isInSocketSet(oslSocketSet Set, oslSocket pSocket)
2422 : {
2423 : TSocketSetImpl* pSet;
2424 :
2425 : OSL_ASSERT(Set);
2426 : OSL_ASSERT(pSocket);
2427 0 : if ( Set == 0 || pSocket == 0 )
2428 : {
2429 0 : return sal_False;
2430 : }
2431 :
2432 0 : pSet= (TSocketSetImpl*)Set;
2433 :
2434 0 : return (FD_ISSET(pSocket->m_Socket, &pSet->m_Set) != 0);
2435 : }
2436 :
2437 0 : sal_Int32 SAL_CALL osl_demultiplexSocketEvents(oslSocketSet IncomingSet,
2438 : oslSocketSet OutgoingSet,
2439 : oslSocketSet OutOfBandSet,
2440 : const TimeValue* pTimeout)
2441 : {
2442 0 : int MaxHandle= 0;
2443 : struct timeval tv;
2444 : TSocketSetImpl* pInSet;
2445 : TSocketSetImpl* pOutSet;
2446 : TSocketSetImpl* pOOBSet;
2447 :
2448 0 : if (pTimeout)
2449 : {
2450 : /* non-blocking call */
2451 0 : tv.tv_sec = pTimeout->Seconds;
2452 0 : tv.tv_usec = pTimeout->Nanosec / 1000L;
2453 : }
2454 :
2455 : /* map opaque data to impl-types */
2456 0 : pInSet= (TSocketSetImpl*)IncomingSet;
2457 0 : pOutSet= (TSocketSetImpl*)OutgoingSet;
2458 0 : pOOBSet= (TSocketSetImpl*)OutOfBandSet;
2459 :
2460 : /* get max handle from all sets */
2461 0 : if (pInSet)
2462 0 : MaxHandle= pInSet->m_MaxHandle;
2463 :
2464 0 : if (pOutSet && (pOutSet->m_MaxHandle > MaxHandle))
2465 0 : MaxHandle= pOutSet->m_MaxHandle;
2466 :
2467 0 : if (pOOBSet && (pOOBSet->m_MaxHandle > MaxHandle))
2468 0 : MaxHandle= pOOBSet->m_MaxHandle;
2469 :
2470 0 : return select(MaxHandle+1,
2471 : pInSet ? PTR_FD_SET(pInSet->m_Set) : 0,
2472 : pOutSet ? PTR_FD_SET(pOutSet->m_Set) : 0,
2473 : pOOBSet ? PTR_FD_SET(pOOBSet->m_Set) : 0,
2474 : pTimeout ? &tv : 0);
2475 : }
2476 :
2477 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|