Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sal/osl/unx/socket.cxx
Line
Count
Source
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 <sal/config.h>
21
22
#include <utility>
23
24
#include "system.hxx"
25
26
#include <osl/socket.h>
27
28
#include <rtl/alloc.h>
29
#include <rtl/byteseq.h>
30
#include <rtl/ustring.hxx>
31
#include <assert.h>
32
#include <sal/types.h>
33
#include <sal/log.hxx>
34
35
#include "sockimpl.hxx"
36
#include "unixerrnostring.hxx"
37
#include <oslsocket.hxx>
38
39
#include <arpa/inet.h>
40
#include <fcntl.h>
41
#include <netdb.h>
42
#ifdef FREEBSD
43
#include <netinet/ip.h>
44
#endif
45
#include <netinet/tcp.h>
46
#include <poll.h>
47
#include <unistd.h>
48
49
/* defines for shutdown */
50
#define SD_RECEIVE 0
51
#define SD_SEND 1
52
#define SD_BOTH 2
53
54
/*
55
    oslSocketAddr is a pointer to a Berkeley struct sockaddr.
56
    I refrained from using sockaddr_in because of possible further
57
    extensions of this socket-interface (IP-NG?).
58
    The intention was to hide all Berkeley data-structures from
59
    direct access past the osl-interface.
60
61
    The current implementation is internet (IP) centered. All
62
    the constructor-functions (osl_create...) take parameters
63
    that will probably make sense only in the IP-environment
64
    (e.g. because of using the dotted-address-format).
65
66
    If the interface will be extended to host other protocol-
67
    families, I expect no externally visible changes in the
68
    existing functions. You'll probably need only new
69
    constructor-functions who take the different address
70
    formats into consideration (maybe a long dotted address
71
    or whatever).
72
*/
73
74
/* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */
75
/* are the same! I don't like it very much but see no other easy way to  */
76
/* conceal the struct sockaddr from the eyes of the user. */
77
78
0
#define OSL_INVALID_SOCKET      -1
79
0
#define OSL_SOCKET_ERROR        -1
80
81
/* Buffer size for getnameinfo */
82
#define MAX_HOSTBUFFER_SIZE 2048
83
84
const unsigned long FamilyMap[]= {
85
    AF_INET,                    /* osl_Socket_FamilyInet    */
86
    AF_IPX,                     /* osl_Socket_FamilyIpx     */
87
    0                           /* osl_Socket_FamilyInvalid */
88
};
89
90
static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
91
0
{
92
0
    oslAddrFamily i= oslAddrFamily(0);
93
94
0
    while(i != osl_Socket_FamilyInvalid)
95
0
    {
96
0
        if(FamilyMap[i] == nativeType)
97
0
            return i;
98
0
        i = static_cast<oslAddrFamily>( i + 1 );
99
0
    }
100
101
0
    return i;
102
0
}
103
104
0
#define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
105
1
#define FAMILY_TO_NATIVE(x) static_cast<short>(FamilyMap[x])
106
107
const sal_uInt32 ProtocolMap[]= {
108
    0,                          /* osl_Socket_ProtocolIp      */
109
    NSPROTO_IPX,                /* osl_Socket_ProtocolIpx     */
110
    NSPROTO_SPX,                /* osl_Socket_ProtocolSpx     */
111
    NSPROTO_SPXII,              /* osl_Socket_ProtocolSpxII   */
112
    0                           /* osl_Socket_ProtocolInvalid */
113
};
114
115
0
#define PROTOCOL_TO_NATIVE(x)   ProtocolMap[x]
116
117
const sal_uInt32 TypeMap[]= {
118
    SOCK_STREAM,                /* osl_Socket_TypeStream    */
119
    SOCK_DGRAM,                 /* osl_Socket_TypeDgram     */
120
    SOCK_RAW,                   /* osl_Socket_TypeRaw       */
121
    SOCK_RDM,                   /* osl_Socket_TypeRdm       */
122
    SOCK_SEQPACKET,             /* osl_Socket_TypeSeqPacket */
123
    0                           /* osl_Socket_TypeInvalid   */
124
};
125
126
static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType)
127
0
{
128
0
    oslSocketType i= oslSocketType(0);
129
130
0
    while(i != osl_Socket_TypeInvalid)
131
0
    {
132
0
        if(TypeMap[i] == nativeType)
133
0
            return i;
134
0
        i = static_cast<oslSocketType>(i + 1);
135
0
    }
136
137
0
    return i;
138
0
}
139
140
0
#define TYPE_TO_NATIVE(x)       TypeMap[x]
141
0
#define TYPE_FROM_NATIVE(y)     osl_SocketTypeFromNative(y)
142
143
const sal_uInt32 OptionMap[]= {
144
    SO_DEBUG,                   /* osl_Socket_OptionDebug       */
145
    SO_ACCEPTCONN,              /* osl_Socket_OptionAcceptConn  */
146
    SO_REUSEADDR,               /* osl_Socket_OptionReuseAddr   */
147
    SO_KEEPALIVE,               /* osl_Socket_OptionKeepAlive   */
148
    SO_DONTROUTE,               /* osl_Socket_OptionDontRoute   */
149
    SO_BROADCAST,               /* osl_Socket_OptionBroadcast   */
150
    SO_USELOOPBACK,             /* osl_Socket_OptionUseLoopback */
151
    SO_LINGER,                  /* osl_Socket_OptionLinger      */
152
    SO_OOBINLINE,               /* osl_Socket_OptionOOBinLine   */
153
    SO_SNDBUF,                  /* osl_Socket_OptionSndBuf      */
154
    SO_RCVBUF,                  /* osl_Socket_OptionRcvBuf      */
155
    SO_SNDLOWAT,                /* osl_Socket_OptionSndLowat    */
156
    SO_RCVLOWAT,                /* osl_Socket_OptionRcvLowat    */
157
    SO_SNDTIMEO,                /* osl_Socket_OptionSndTimeo    */
158
    SO_RCVTIMEO,                /* osl_Socket_OptionRcvTimeo    */
159
    SO_ERROR,                   /* osl_Socket_OptionError       */
160
    SO_TYPE,                    /* osl_Socket_OptionType        */
161
    TCP_NODELAY,                /* osl_Socket_OptionTcpNoDelay  */
162
    0                           /* osl_Socket_OptionInvalid     */
163
};
164
165
0
#define OPTION_TO_NATIVE(x)     OptionMap[x]
166
167
const sal_uInt32 OptionLevelMap[]= {
168
    SOL_SOCKET,                 /* osl_Socket_LevelSocket  */
169
    IPPROTO_TCP,                /* osl_Socket_LevelTcp     */
170
    0                           /* osl_Socket_LevelInvalid */
171
};
172
173
0
#define OPTION_LEVEL_TO_NATIVE(x)       OptionLevelMap[x]
174
175
const sal_uInt32 SocketMsgFlagMap[]= {
176
    0,                          /* osl_Socket_MsgNormal    */
177
    MSG_OOB,                    /* osl_Socket_MsgOOB       */
178
    MSG_PEEK,                   /* osl_Socket_MsgPeek      */
179
    MSG_DONTROUTE,              /* osl_Socket_MsgDontRoute */
180
    MSG_MAXIOVLEN,              /* osl_Socket_MsgMaxIOVLen */
181
    0                           /* osl_Socket_MsgInvalid   */
182
};
183
184
0
#define MSG_FLAG_TO_NATIVE(x)       SocketMsgFlagMap[x]
185
186
const sal_uInt32 SocketDirection[]= {
187
    SD_RECEIVE,                 /* osl_Socket_DirRead      */
188
    SD_SEND,                    /* osl_Socket_DirWrite     */
189
    SD_BOTH,                    /* osl_Socket_DirReadWrite */
190
    0                           /* osl_Socket_DirInvalid   */
191
};
192
193
0
#define DIRECTION_TO_NATIVE(x)      SocketDirection[x]
194
195
const struct
196
{
197
    int            errcode;
198
    oslSocketError error;
199
} SocketError[]= {
200
    { 0,               osl_Socket_E_None              }, /* no error */
201
    { ENOTSOCK,        osl_Socket_E_NotSocket         }, /* Socket operation on non-socket */
202
    { EDESTADDRREQ,    osl_Socket_E_DestAddrReq       }, /* Destination address required */
203
    { EMSGSIZE,        osl_Socket_E_MsgSize           }, /* Message too long */
204
    { EPROTOTYPE,      osl_Socket_E_Prototype         }, /* Protocol wrong type for socket */
205
    { ENOPROTOOPT,     osl_Socket_E_NoProtocol        }, /* Protocol not available */
206
    { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */
207
#ifdef ESOCKTNOSUPPORT
208
    { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport     }, /* Socket type not supported */
209
#endif
210
    { EOPNOTSUPP,      osl_Socket_E_OpNotSupport      }, /* Operation not supported on socket */
211
    { EPFNOSUPPORT,    osl_Socket_E_PfNoSupport       }, /* Protocol family not supported */
212
    { EAFNOSUPPORT,    osl_Socket_E_AfNoSupport       }, /* Address family not supported by
213
                                                            protocol family */
214
    { EADDRINUSE,      osl_Socket_E_AddrInUse         }, /* Address already in use */
215
    { EADDRNOTAVAIL,   osl_Socket_E_AddrNotAvail      }, /* Can't assign requested address */
216
    { ENETDOWN,        osl_Socket_E_NetDown           }, /* Network is down */
217
    { ENETUNREACH,     osl_Socket_E_NetUnreachable    }, /* Network is unreachable */
218
    { ENETRESET,       osl_Socket_E_NetReset          }, /* Network dropped connection because
219
                                                            of reset */
220
    { ECONNABORTED,    osl_Socket_E_ConnAborted       }, /* Software caused connection abort */
221
    { ECONNRESET,      osl_Socket_E_ConnReset         }, /* Connection reset by peer */
222
    { ENOBUFS,         osl_Socket_E_NoBufferSpace     }, /* No buffer space available */
223
    { EISCONN,         osl_Socket_E_IsConnected       }, /* Socket is already connected */
224
    { ENOTCONN,        osl_Socket_E_NotConnected      }, /* Socket is not connected */
225
    { ESHUTDOWN,       osl_Socket_E_Shutdown          }, /* Can't send after socket shutdown */
226
#ifdef ETOOMANYREFS
227
    { ETOOMANYREFS,    osl_Socket_E_TooManyRefs       }, /* Too many references: can't splice */
228
#endif
229
    { ETIMEDOUT,       osl_Socket_E_TimedOut          }, /* Connection timed out */
230
    { ECONNREFUSED,    osl_Socket_E_ConnRefused       }, /* Connection refused */
231
    { EHOSTDOWN,       osl_Socket_E_HostDown          }, /* Host is down */
232
    { EHOSTUNREACH,    osl_Socket_E_HostUnreachable   }, /* No route to host */
233
    { EWOULDBLOCK,     osl_Socket_E_WouldBlock        }, /* call would block on non-blocking socket */
234
    { EALREADY,        osl_Socket_E_Already           }, /* operation already in progress */
235
    { EINPROGRESS,     osl_Socket_E_InProgress        }, /* operation now in progress */
236
    { EAGAIN,          osl_Socket_E_WouldBlock        }, /* same as EWOULDBLOCK */
237
    { -1,              osl_Socket_E_InvalidError      }
238
};
239
240
static oslSocketError osl_SocketErrorFromNative(int nativeType)
241
0
{
242
0
    int i = 0;
243
244
0
    while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
245
0
           (SocketError[i].errcode != nativeType)) i++;
246
247
0
    return SocketError[i].error;
248
0
}
249
250
0
#define ERROR_FROM_NATIVE(y)    osl_SocketErrorFromNative(y)
251
252
static oslSocketAddr osl_psz_createInetSocketAddr (
253
    const char* pszDottedAddr, sal_Int32 Port);
254
255
static oslHostAddr osl_psz_createHostAddr (
256
    const char *pszHostname, const oslSocketAddr Addr);
257
258
static oslHostAddr osl_psz_createHostAddrByName (
259
    const char *pszHostname);
260
261
static const char* osl_psz_getHostnameOfHostAddr (
262
    const oslHostAddr Addr);
263
264
static oslSocketAddr osl_psz_resolveHostname (
265
    const char* pszHostname);
266
267
static sal_Int32 osl_psz_getServicePort (
268
    const char* pszServicename, const char* pszProtocol);
269
270
static void osl_psz_getLastSocketErrorDescription (
271
    oslSocket Socket, char* pBuffer, sal_uInt32 BufferSize);
272
273
namespace {
274
275
0
int convertToMs(TimeValue const * value) {
276
0
    return value->Seconds * 1000 + value->Nanosec / 1000000; //TODO: overflow
277
0
}
278
279
}
280
281
static oslSocket createSocketImpl()
282
0
{
283
0
    oslSocket pSocket;
284
285
0
    pSocket = static_cast<oslSocket>(calloc(1, sizeof(struct oslSocketImpl)));
286
287
0
    pSocket->m_Socket = OSL_INVALID_SOCKET;
288
0
    pSocket->m_nLastError = 0;
289
0
    pSocket->m_nRefCount = 1;
290
291
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
292
0
    pSocket->m_bIsAccepting = false;
293
0
#endif
294
295
0
    return pSocket;
296
0
}
297
298
static void destroySocketImpl(oslSocket Socket)
299
0
{
300
0
    if ( Socket != nullptr)
301
0
        free(Socket);
302
0
}
303
304
static oslSocketAddr createSocketAddr()
305
1
{
306
1
    oslSocketAddr pAddr = static_cast<oslSocketAddr>(rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl )));
307
1
    return pAddr;
308
1
}
309
310
static oslSocketAddr createSocketAddrWithFamily(
311
    oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
312
0
{
313
0
    oslSocketAddr pAddr;
314
315
0
    SAL_WARN_IF( family != osl_Socket_FamilyInet, "sal.osl", "creating socket for non-IP address family" );
316
317
0
    pAddr = createSocketAddr();
318
0
    switch( family )
319
0
    {
320
0
    case osl_Socket_FamilyInet:
321
0
    {
322
0
        struct sockaddr_in* pInetAddr= reinterpret_cast<sockaddr_in*>(&pAddr->m_sockaddr);
323
324
0
        pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
325
0
        pInetAddr->sin_addr.s_addr = nAddr;
326
0
        pInetAddr->sin_port = static_cast<sal_uInt16>(port&0xffff);
327
0
        break;
328
0
       }
329
0
    default:
330
0
        pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
331
0
    }
332
0
    return pAddr;
333
0
}
334
335
static oslSocketAddr createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
336
0
{
337
0
    oslSocketAddr pAddr = createSocketAddr();
338
0
    memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) );
339
0
    return pAddr;
340
0
}
341
342
static void destroySocketAddr( oslSocketAddr addr )
343
1
{
344
1
    free( addr );
345
1
}
346
347
oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
348
0
{
349
0
    oslSocketAddr pAddr = nullptr;
350
351
    /* is it an internet-Addr? */
352
0
    if (Family == osl_Socket_FamilyInet)
353
0
    {
354
0
        pAddr = createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
355
0
    }
356
0
    else
357
0
    {
358
0
        pAddr = createSocketAddrWithFamily( Family , 0 , 0 );
359
0
    }
360
361
0
    return pAddr;
362
0
}
363
364
oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
365
0
{
366
0
    oslSocketAddr pCopy = nullptr;
367
0
    if (Addr)
368
0
    {
369
0
        pCopy = createSocketAddr();
370
371
0
        if (pCopy)
372
0
            memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
373
0
    }
374
0
    return pCopy;
375
0
}
376
377
sal_Bool SAL_CALL osl_isEqualSocketAddr (
378
    oslSocketAddr Addr1,
379
    oslSocketAddr Addr2)
380
0
{
381
0
    struct sockaddr* pAddr1 = nullptr;
382
0
    struct sockaddr* pAddr2 = nullptr;
383
384
0
    assert(Addr1 && Addr2);
385
0
    pAddr1 = &(Addr1->m_sockaddr);
386
0
    pAddr2 = &(Addr2->m_sockaddr);
387
388
0
    if (pAddr1 == pAddr2)
389
0
    {
390
0
        return true;
391
0
    }
392
393
0
    if (pAddr1->sa_family == pAddr2->sa_family)
394
0
    {
395
0
        switch (pAddr1->sa_family)
396
0
        {
397
0
            case AF_INET:
398
0
            {
399
0
                struct sockaddr_in* pInetAddr1= reinterpret_cast<sockaddr_in*>(pAddr1);
400
0
                struct sockaddr_in* pInetAddr2= reinterpret_cast<sockaddr_in*>(pAddr2);
401
402
0
                if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
403
0
                    (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
404
0
                    (pInetAddr1->sin_port == pInetAddr2->sin_port))
405
0
                    return true;
406
0
                [[fallthrough]];
407
0
            }
408
409
0
            default:
410
0
            {
411
0
                return (memcmp(pAddr1, pAddr2, sizeof(struct sockaddr)) == 0);
412
0
            }
413
0
        }
414
0
    }
415
416
0
    return false;
417
0
}
418
419
oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
420
    rtl_uString *strDottedAddr,
421
    sal_Int32    Port)
422
0
{
423
0
    sal_uInt32    nAddr = OSL_INADDR_NONE;
424
0
    oslSocketAddr pAddr;
425
426
0
    if (strDottedAddr && strDottedAddr->length)
427
0
    {
428
        /* Dotted host address for limited broadcast */
429
0
        rtl_String *pDottedAddr = nullptr;
430
431
0
        rtl_uString2String (
432
0
            &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
433
0
            RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
434
435
0
        in_addr buf;
436
0
        if (inet_pton (AF_INET, pDottedAddr->buffer, &buf) == 1) {
437
0
            nAddr = buf.s_addr;
438
0
        }
439
0
        rtl_string_release (pDottedAddr);
440
0
    }
441
442
0
    if (nAddr != OSL_INADDR_NONE)
443
0
    {
444
        /* Limited broadcast */
445
0
        nAddr = ntohl(nAddr);
446
0
        if (IN_CLASSA(nAddr))
447
0
        {
448
0
            nAddr &= IN_CLASSA_NET;
449
0
            nAddr |= IN_CLASSA_HOST;
450
0
        }
451
0
        else if (IN_CLASSB(nAddr))
452
0
        {
453
0
            nAddr &= IN_CLASSB_NET;
454
0
            nAddr |= IN_CLASSB_HOST;
455
0
        }
456
0
        else if (IN_CLASSC(nAddr))
457
0
        {
458
0
            nAddr &= IN_CLASSC_NET;
459
0
            nAddr |= IN_CLASSC_HOST;
460
0
        }
461
0
        else
462
0
        {
463
            /* No broadcast in class D */
464
0
            return nullptr;
465
0
        }
466
0
        nAddr = htonl(nAddr);
467
0
    }
468
469
0
    pAddr = createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
470
0
    return pAddr;
471
0
}
472
473
oslSocketAddr SAL_CALL osl_createInetSocketAddr (
474
    rtl_uString *ustrDottedAddr,
475
    sal_Int32    Port)
476
0
{
477
0
    rtl_String* strDottedAddr=nullptr;
478
0
    oslSocketAddr Addr;
479
0
    char* pszDottedAddr=nullptr;
480
481
0
    if ( ustrDottedAddr != nullptr )
482
0
    {
483
0
        rtl_uString2String( &strDottedAddr,
484
0
                            rtl_uString_getStr(ustrDottedAddr),
485
0
                            rtl_uString_getLength(ustrDottedAddr),
486
0
                            RTL_TEXTENCODING_UTF8,
487
0
                            OUSTRING_TO_OSTRING_CVTFLAGS);
488
0
        pszDottedAddr = rtl_string_getStr(strDottedAddr);
489
0
    }
490
491
0
    Addr = pszDottedAddr ? osl_psz_createInetSocketAddr(pszDottedAddr, Port) : nullptr;
492
493
0
    if ( strDottedAddr != nullptr )
494
0
    {
495
0
        rtl_string_release(strDottedAddr);
496
0
    }
497
498
0
    return Addr;
499
0
}
500
501
oslSocketAddr osl_psz_createInetSocketAddr (
502
    const char* pszDottedAddr,
503
    sal_Int32       Port)
504
0
{
505
0
    oslSocketAddr pAddr = nullptr;
506
0
    in_addr buf;
507
0
    if(inet_pton(AF_INET, pszDottedAddr, &buf) == 1)
508
0
    {
509
        /* valid dotted addr */
510
0
        pAddr = createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , buf.s_addr );
511
0
    }
512
0
    return pAddr;
513
0
}
514
515
oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
516
0
{
517
0
    oslSocketResult res = osl_Socket_Error;
518
519
0
    SAL_WARN_IF( !pAddr, "sal.osl", "setting address of undefined socket address" );
520
0
    SAL_WARN_IF( !pByteSeq, "sal.osl", "setting undefined address for socket address" );
521
522
0
    if( pAddr && pByteSeq )
523
0
    {
524
0
        struct sockaddr_in * pSystemInetAddr;
525
526
0
        assert( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
527
0
        assert( pByteSeq->nElements == 4 );
528
529
0
        pSystemInetAddr = reinterpret_cast<sockaddr_in *>(&pAddr->m_sockaddr);
530
0
        memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
531
0
        res = osl_Socket_Ok;
532
0
    }
533
0
    return res;
534
0
}
535
536
oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
537
0
{
538
0
    oslSocketResult res = osl_Socket_Error;
539
540
0
    SAL_WARN_IF( !pAddr, "sal.osl", "getting address of undefined socket address" );
541
0
    SAL_WARN_IF( !ppByteSeq, "sal.osl", "getting address to undefined address pointer" );
542
543
0
    if( pAddr && ppByteSeq )
544
0
    {
545
0
        struct sockaddr_in * pSystemInetAddr = reinterpret_cast<sockaddr_in *>(&pAddr->m_sockaddr);
546
0
        rtl_byte_sequence_constructFromArray( ppByteSeq, reinterpret_cast<sal_Int8 *>(&pSystemInetAddr->sin_addr), 4);
547
0
        res = osl_Socket_Ok;
548
0
    }
549
0
    return res;
550
0
}
551
552
/** try to figure out a full-qualified hostname, by adding the current domain
553
    as given by the domainname program to the given hostname.
554
    This function MUST NOT call gethostbyname since pHostName already points
555
    to data returned by gethostname and would be garbled: use gethostname_r
556
    instead!
557
 */
558
559
namespace {
560
561
struct oslAddrInfo
562
{
563
    addrinfo* pAddrInfoList = nullptr;
564
    int nError;
565
566
    oslAddrInfo(const char* name, bool isInet = false)
567
2
    {
568
2
        addrinfo aHints;
569
2
        memset(&aHints, 0, sizeof(addrinfo));
570
2
        if (isInet)
571
1
            aHints.ai_family = AF_INET;
572
2
        aHints.ai_flags = AI_CANONNAME;
573
574
2
        nError = getaddrinfo(name, nullptr, &aHints, &pAddrInfoList);
575
2
    }
576
577
    ~oslAddrInfo()
578
2
    {
579
2
        if (nError == 0)
580
2
            freeaddrinfo(pAddrInfoList);
581
2
    }
582
583
    const char* getHostName() const
584
1
    {
585
1
        assert(pAddrInfoList);
586
1
        return pAddrInfoList->ai_canonname;
587
1
    }
588
};
589
590
}
591
static bool isFullQualifiedDomainName (const char *pHostName)
592
1
{
593
    /* a FQDN (aka 'hostname.domain.top_level_domain' )
594
     * is a name which contains a dot '.' in it ( would
595
     * match as well for 'hostname.' but is good enough
596
     * for now )*/
597
1
    return strchr( pHostName, int('.') ) != nullptr;
598
1
}
599
600
static char* getFullQualifiedDomainName (const char *pHostName)
601
1
{
602
1
    char  *pFullQualifiedName = nullptr;
603
604
1
    if (isFullQualifiedDomainName(pHostName))
605
0
    {
606
0
        pFullQualifiedName = strdup(pHostName);
607
0
    }
608
1
    else
609
1
    {
610
1
        oslAddrInfo aAddrInfo(pHostName);
611
1
        if (aAddrInfo.nError == 0)
612
1
            pFullQualifiedName = strdup(aAddrInfo.getHostName());
613
1
    }
614
615
1
    return pFullQualifiedName;
616
1
}
617
618
struct oslHostAddrImpl
619
{
620
    char        *pHostName;
621
    oslSocketAddr   pSockAddr;
622
};
623
624
static oslHostAddr addrinfoToHostAddr (const addrinfo* ai)
625
1
{
626
1
    if (!ai || !ai->ai_canonname || !ai->ai_addr)
627
0
        return nullptr;
628
629
1
    char* cn = getFullQualifiedDomainName(ai->ai_canonname);
630
1
    SAL_WARN_IF( !cn, "sal.osl", "couldn't get full qualified domain name" );
631
1
    if (cn == nullptr)
632
0
        return nullptr;
633
634
1
    oslSocketAddr pSockAddr = createSocketAddr();
635
1
    SAL_WARN_IF( !pSockAddr, "sal.osl", "insufficient memory" );
636
1
    if (pSockAddr == nullptr)
637
0
    {
638
0
        free(cn);
639
0
        return nullptr;
640
0
    }
641
642
1
    if (ai->ai_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
643
1
    {
644
1
        memcpy (
645
1
            &(pSockAddr->m_sockaddr),
646
1
            ai->ai_addr,
647
1
            ai->ai_addrlen);
648
1
    }
649
0
    else
650
0
    {
651
        /* unknown address family */
652
        /* future extensions for new families might be implemented here */
653
654
0
        SAL_WARN( "sal.osl", "unknown address family" );
655
656
0
        destroySocketAddr( pSockAddr );
657
0
        free (cn);
658
0
        return nullptr;
659
0
    }
660
661
1
    oslHostAddr pAddr = static_cast<oslHostAddr>(malloc(sizeof(struct oslHostAddrImpl)));
662
1
    SAL_WARN_IF( !pAddr, "sal.osl", "allocation error" );
663
1
    if (pAddr == nullptr)
664
0
    {
665
0
        destroySocketAddr( pSockAddr );
666
0
        free (cn);
667
0
        return nullptr;
668
0
    }
669
670
1
    pAddr->pHostName= cn;
671
1
    pAddr->pSockAddr= pSockAddr;
672
673
1
    return pAddr;
674
1
}
675
676
oslHostAddr SAL_CALL osl_createHostAddr (
677
    rtl_uString        *ustrHostname,
678
    const oslSocketAddr Addr)
679
0
{
680
0
    oslHostAddr HostAddr;
681
0
    rtl_String* strHostname=nullptr;
682
0
    char* pszHostName=nullptr;
683
684
0
    if ( ustrHostname != nullptr )
685
0
    {
686
0
        rtl_uString2String( &strHostname,
687
0
                            rtl_uString_getStr(ustrHostname),
688
0
                            rtl_uString_getLength(ustrHostname),
689
0
                            RTL_TEXTENCODING_UTF8,
690
0
                            OUSTRING_TO_OSTRING_CVTFLAGS );
691
0
        pszHostName = rtl_string_getStr(strHostname);
692
0
    }
693
694
0
    HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
695
696
0
    if ( strHostname != nullptr )
697
0
    {
698
0
        rtl_string_release(strHostname);
699
0
    }
700
701
0
    return HostAddr;
702
0
}
703
704
oslHostAddr osl_psz_createHostAddr (
705
    const char     *pszHostname,
706
    const oslSocketAddr pAddr)
707
0
{
708
0
    oslHostAddr pHostAddr;
709
0
    char            *cn;
710
711
0
    SAL_WARN_IF( !pszHostname, "sal.osl", "undefined hostname" );
712
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
713
0
    if ((pszHostname == nullptr) || (pAddr == nullptr))
714
0
        return nullptr;
715
716
0
    cn = strdup(pszHostname);
717
0
    SAL_WARN_IF( !cn, "sal.osl", "insufficient memory" );
718
0
    if (cn == nullptr)
719
0
        return nullptr;
720
721
0
    pHostAddr= static_cast<oslHostAddr>(malloc(sizeof(struct oslHostAddrImpl)));
722
0
    SAL_WARN_IF( !pHostAddr, "sal.osl", "allocation error" );
723
0
    if (pHostAddr == nullptr)
724
0
    {
725
0
        free (cn);
726
0
        return nullptr;
727
0
    }
728
729
0
    pHostAddr->pHostName= cn;
730
0
    pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
731
732
0
    return pHostAddr;
733
0
}
734
735
oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
736
0
{
737
0
    oslHostAddr HostAddr;
738
0
    rtl_String* strHostname=nullptr;
739
0
    char* pszHostName=nullptr;
740
741
0
    if ( ustrHostname != nullptr )
742
0
    {
743
0
        rtl_uString2String( &strHostname,
744
0
                            rtl_uString_getStr(ustrHostname),
745
0
                            rtl_uString_getLength(ustrHostname),
746
0
                            RTL_TEXTENCODING_UTF8,
747
0
                            OUSTRING_TO_OSTRING_CVTFLAGS );
748
0
        pszHostName=rtl_string_getStr(strHostname);
749
0
    }
750
751
0
    HostAddr = osl_psz_createHostAddrByName(pszHostName);
752
753
0
    if ( strHostname != nullptr )
754
0
    {
755
0
        rtl_string_release(strHostname);
756
0
    }
757
758
0
    return HostAddr;
759
0
}
760
761
oslHostAddr osl_psz_createHostAddrByName (const char *pszHostname)
762
1
{
763
1
    oslAddrInfo aAddrInfo(pszHostname, /* isInet */ true);
764
765
1
    return addrinfoToHostAddr (aAddrInfo.pAddrInfoList);
766
1
}
767
768
oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
769
0
{
770
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
771
772
0
    if (pAddr == nullptr)
773
0
        return nullptr;
774
775
0
    if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
776
0
    {
777
0
        const struct sockaddr_in *sin = reinterpret_cast<sockaddr_in *>(&pAddr->m_sockaddr);
778
0
        if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
779
0
            return nullptr;
780
781
0
        char host[MAX_HOSTBUFFER_SIZE];
782
0
        int res = getnameinfo(&pAddr->m_sockaddr, sizeof(struct sockaddr_in),
783
0
                              host, sizeof(host), nullptr, 0, NI_NAMEREQD);
784
0
        if (res != 0)
785
0
            return nullptr;
786
787
0
        char *cn = getFullQualifiedDomainName(host);
788
0
        SAL_WARN_IF( !cn, "sal.osl", "couldn't get full qualified domain name" );
789
0
        if (cn == nullptr)
790
0
            return nullptr;
791
792
0
        oslSocketAddr pSockAddr = createSocketAddr();
793
0
        SAL_WARN_IF( !pSockAddr, "sal.osl", "insufficient memory" );
794
0
        if (pSockAddr == nullptr)
795
0
        {
796
0
            free(cn);
797
0
            return nullptr;
798
0
        }
799
800
0
        memcpy(&pSockAddr->m_sockaddr, &pAddr->m_sockaddr, sizeof(pAddr->m_sockaddr));
801
802
0
        oslHostAddr pHostAddr = static_cast<oslHostAddr>(malloc(sizeof(struct oslHostAddrImpl)));
803
0
        SAL_WARN_IF( !pAddr, "sal.osl", "allocation error" );
804
0
        if (pHostAddr == nullptr)
805
0
        {
806
0
            destroySocketAddr(pSockAddr);
807
0
            free(cn);
808
0
            return nullptr;
809
0
        }
810
811
0
        pHostAddr->pHostName = cn;
812
0
        pHostAddr->pSockAddr = pSockAddr;
813
814
0
        return pHostAddr;
815
0
    }
816
817
0
    return nullptr;
818
0
}
819
820
oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr)
821
0
{
822
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
823
824
0
    if (pAddr)
825
0
        return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
826
0
    return nullptr;
827
0
}
828
829
void SAL_CALL osl_getHostnameOfHostAddr (
830
    const oslHostAddr   Addr,
831
    rtl_uString       **ustrHostname)
832
0
{
833
0
    const char* pHostname = osl_psz_getHostnameOfHostAddr(Addr);
834
835
0
    rtl_uString_newFromAscii (ustrHostname, pHostname);
836
0
}
837
838
const char* osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
839
1
{
840
1
    if (pAddr)
841
1
        return pAddr->pHostName;
842
0
    return nullptr;
843
1
}
844
845
oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
846
0
{
847
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
848
849
0
    if (pAddr)
850
0
        return pAddr->pSockAddr;
851
0
    return nullptr;
852
0
}
853
854
void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
855
1
{
856
1
    if (pAddr)
857
1
    {
858
1
        if (pAddr->pHostName)
859
1
            free (pAddr->pHostName);
860
1
        if (pAddr->pSockAddr)
861
1
            osl_destroySocketAddr (pAddr->pSockAddr);
862
1
        free (pAddr);
863
1
    }
864
1
}
865
866
namespace
867
{
868
std::pair<oslSocketResult, OUString> lcl_getLocalHostname(bool bUseFQDN)
869
1
{
870
1
    char LocalHostname[256] = "";
871
872
#ifdef SYSV
873
    struct utsname uts;
874
875
    if (uname(&uts) < 0)
876
        return {osl_Socket_Error, OUString()};
877
878
    if ((strlen(uts.nodename) + 1) > nBufLen)
879
        return {osl_Socket_Error, OUString()};
880
881
    strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
882
#else  /* BSD compatible */
883
1
    if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
884
0
        return {osl_Socket_Error, OUString()};
885
1
#endif /* SYSV */
886
1
    LocalHostname[sizeof(LocalHostname)-1] = 0;
887
888
    /* check if we have an FQDN */
889
1
    if (bUseFQDN && strchr(LocalHostname, '.') == nullptr)
890
1
    {
891
1
        oslHostAddr Addr;
892
893
        /* no, determine it via dns */
894
1
        Addr = osl_psz_createHostAddrByName(LocalHostname);
895
896
1
        const char *pStr;
897
1
        if ((pStr = osl_psz_getHostnameOfHostAddr(Addr)) != nullptr)
898
1
        {
899
1
            strncpy(LocalHostname, pStr, sizeof( LocalHostname ));
900
1
            LocalHostname[sizeof(LocalHostname)-1] = 0;
901
1
        }
902
1
        osl_destroyHostAddr(Addr);
903
1
    }
904
905
1
    if (LocalHostname[0] != '\0')
906
1
    {
907
1
        return {osl_Socket_Ok, OUString::createFromAscii(LocalHostname)};
908
1
    }
909
910
0
    return {osl_Socket_Error, OUString()};
911
1
}
912
913
} // anonymous namespace
914
915
oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
916
0
{
917
0
    static auto const init = lcl_getLocalHostname(/*bUseFQDN*/false);
918
919
0
    rtl_uString_assign(ustrLocalHostname,init.second.pData);
920
0
    return init.first;
921
0
}
922
923
oslSocketResult osl_getLocalHostnameFQDN(rtl_uString **ustrLocalHostname)
924
160
{
925
160
    static auto const init = lcl_getLocalHostname(/*bUseFQDN*/true);
926
927
160
    rtl_uString_assign(ustrLocalHostname,init.second.pData);
928
160
    return init.first;
929
160
}
930
931
oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
932
0
{
933
0
    oslSocketAddr Addr;
934
0
    rtl_String* strHostname=nullptr;
935
0
    char* pszHostName=nullptr;
936
937
0
    if ( ustrHostname != nullptr )
938
0
    {
939
0
        rtl_uString2String( &strHostname,
940
0
                            rtl_uString_getStr(ustrHostname),
941
0
                            rtl_uString_getLength(ustrHostname),
942
0
                            RTL_TEXTENCODING_UTF8,
943
0
                            OUSTRING_TO_OSTRING_CVTFLAGS );
944
0
        pszHostName = rtl_string_getStr(strHostname);
945
0
    }
946
947
0
    Addr = osl_psz_resolveHostname(pszHostName);
948
949
0
    if ( strHostname != nullptr )
950
0
    {
951
0
        rtl_string_release(strHostname);
952
0
    }
953
954
0
    return Addr;
955
0
}
956
957
oslSocketAddr osl_psz_resolveHostname(const char* pszHostname)
958
0
{
959
0
    struct oslHostAddrImpl *pAddr = osl_psz_createHostAddrByName(pszHostname);
960
961
0
    if (pAddr)
962
0
    {
963
0
        oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr);
964
965
0
        osl_destroyHostAddr(pAddr);
966
967
0
        return SockAddr;
968
0
    }
969
970
0
    return nullptr;
971
0
}
972
973
sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol)
974
0
{
975
0
    sal_Int32 nPort;
976
0
    rtl_String* strServicename=nullptr;
977
0
    rtl_String* strProtocol=nullptr;
978
0
    char* pszServiceName=nullptr;
979
0
    char* pszProtocol=nullptr;
980
981
0
    if ( ustrServicename != nullptr )
982
0
    {
983
0
        rtl_uString2String( &strServicename,
984
0
                            rtl_uString_getStr(ustrServicename),
985
0
                            rtl_uString_getLength(ustrServicename),
986
0
                            RTL_TEXTENCODING_UTF8,
987
0
                            OUSTRING_TO_OSTRING_CVTFLAGS );
988
0
        pszServiceName = rtl_string_getStr(strServicename);
989
0
    }
990
991
0
    if ( ustrProtocol != nullptr )
992
0
    {
993
0
        rtl_uString2String( &strProtocol,
994
0
                            rtl_uString_getStr(ustrProtocol),
995
0
                            rtl_uString_getLength(ustrProtocol),
996
0
                            RTL_TEXTENCODING_UTF8,
997
0
                            OUSTRING_TO_OSTRING_CVTFLAGS );
998
0
        pszProtocol = rtl_string_getStr(strProtocol);
999
0
    }
1000
1001
0
    nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
1002
1003
0
    if ( strServicename != nullptr )
1004
0
    {
1005
0
        rtl_string_release(strServicename);
1006
0
    }
1007
1008
0
    if ( strProtocol != nullptr )
1009
0
    {
1010
0
        rtl_string_release(strProtocol);
1011
0
    }
1012
1013
0
    return nPort;
1014
0
}
1015
1016
sal_Int32 osl_psz_getServicePort(const char* pszServicename,
1017
                        const char* pszProtocol)
1018
0
{
1019
0
    struct servent* ps;
1020
1021
0
    ps= getservbyname(pszServicename, pszProtocol);
1022
1023
0
    if (ps != nullptr)
1024
0
        return ntohs(ps->s_port);
1025
1026
0
    return OSL_INVALID_PORT;
1027
0
}
1028
1029
void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
1030
1
{
1031
1
    destroySocketAddr( pAddr );
1032
1
}
1033
1034
oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
1035
0
{
1036
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1037
1038
0
    if (pAddr)
1039
0
        return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
1040
0
    return osl_Socket_FamilyInvalid;
1041
0
}
1042
1043
sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
1044
0
{
1045
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1046
1047
0
    if( pAddr )
1048
0
    {
1049
0
        struct sockaddr_in* pSystemInetAddr= reinterpret_cast<sockaddr_in*>(&pAddr->m_sockaddr);
1050
1051
0
        if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1052
0
            return ntohs(pSystemInetAddr->sin_port);
1053
0
    }
1054
0
    return OSL_INVALID_PORT;
1055
0
}
1056
1057
sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port)
1058
0
{
1059
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1060
1061
0
    if( pAddr )
1062
0
    {
1063
0
        struct sockaddr_in* pSystemInetAddr= reinterpret_cast<sockaddr_in*>(&pAddr->m_sockaddr);
1064
0
        if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1065
0
        {
1066
0
            pSystemInetAddr->sin_port= htons(static_cast<short>(Port));
1067
0
            return true;
1068
0
        }
1069
0
    }
1070
1071
    /* this is not a inet-addr => can't set port */
1072
0
    return false;
1073
0
}
1074
1075
oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
1076
0
{
1077
0
    oslHostAddr pHostAddr= osl_createHostAddrByAddr(Addr);
1078
1079
0
    if (!pHostAddr)
1080
0
    {
1081
0
        return osl_Socket_Error;
1082
0
    }
1083
1084
0
    rtl_uString_newFromAscii(ustrHostname,pHostAddr->pHostName);
1085
1086
0
    osl_destroyHostAddr(pHostAddr);
1087
1088
0
    return osl_Socket_Ok;
1089
0
}
1090
1091
oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
1092
0
{
1093
0
    if( !Addr )
1094
0
    {
1095
0
        return osl_Socket_Error;
1096
0
    }
1097
1098
0
    struct sockaddr_in* pSystemInetAddr = reinterpret_cast<sockaddr_in *>(&Addr->m_sockaddr);
1099
1100
0
    if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
1101
0
    {
1102
0
        return osl_Socket_Error;
1103
0
    }
1104
1105
0
    char buf[INET_ADDRSTRLEN];
1106
0
    auto const text = inet_ntop(AF_INET, &pSystemInetAddr->sin_addr, buf, INET_ADDRSTRLEN);
1107
0
    assert(text != nullptr);
1108
0
    rtl_uString_newFromAscii(ustrDottedInetAddr,text);
1109
1110
0
    return osl_Socket_Ok;
1111
1112
0
}
1113
1114
oslSocket SAL_CALL osl_createSocket(
1115
    oslAddrFamily Family,
1116
    oslSocketType Type,
1117
    oslProtocol Protocol)
1118
0
{
1119
0
    oslSocket pSocket;
1120
1121
    /* alloc memory */
1122
0
    pSocket= createSocketImpl();
1123
1124
    /* create socket */
1125
0
    pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
1126
0
                                TYPE_TO_NATIVE(Type),
1127
0
                                PROTOCOL_TO_NATIVE(Protocol));
1128
1129
    /* creation failed => free memory */
1130
0
    if(pSocket->m_Socket == OSL_INVALID_SOCKET)
1131
0
    {
1132
0
        int nErrno = errno;
1133
0
        SAL_WARN( "sal.osl", "socket creation failed: " << UnixErrnoString(nErrno) );
1134
1135
0
        destroySocketImpl(pSocket);
1136
0
        pSocket= nullptr;
1137
0
    }
1138
0
    else
1139
0
    {
1140
0
        sal_Int32 nFlags=0;
1141
        /* set close-on-exec flag */
1142
0
        if ((nFlags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
1143
0
        {
1144
0
            nFlags |= FD_CLOEXEC;
1145
0
            if (fcntl(pSocket->m_Socket, F_SETFD, nFlags) == -1)
1146
0
            {
1147
0
                pSocket->m_nLastError=errno;
1148
0
                int nErrno = errno;
1149
0
                SAL_WARN( "sal.osl", "failed changing socket flags: " << UnixErrnoString(nErrno) );
1150
0
            }
1151
0
        }
1152
0
        else
1153
0
        {
1154
0
            pSocket->m_nLastError=errno;
1155
0
        }
1156
0
    }
1157
1158
0
    return pSocket;
1159
0
}
1160
1161
void SAL_CALL osl_acquireSocket(oslSocket pSocket)
1162
0
{
1163
0
    osl_atomic_increment(&(pSocket->m_nRefCount));
1164
0
}
1165
1166
void SAL_CALL osl_releaseSocket(oslSocket pSocket)
1167
0
{
1168
0
    if (pSocket && osl_atomic_decrement(&(pSocket->m_nRefCount)) == 0)
1169
0
    {
1170
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1171
0
        if (pSocket->m_bIsAccepting)
1172
0
        {
1173
0
            SAL_WARN( "sal.osl", "attempt to destroy socket while accepting" );
1174
0
            return;
1175
0
        }
1176
0
#endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1177
0
        osl_closeSocket(pSocket);
1178
0
        destroySocketImpl(pSocket);
1179
0
    }
1180
0
}
1181
1182
void SAL_CALL osl_closeSocket(oslSocket pSocket)
1183
0
{
1184
    /* socket already invalid */
1185
0
    if (!pSocket)
1186
0
        return;
1187
1188
0
    pSocket->m_nLastError=0;
1189
0
    sal_Int32 nFD = pSocket->m_Socket;
1190
1191
0
    if (nFD == OSL_INVALID_SOCKET)
1192
0
        return;
1193
1194
0
    pSocket->m_Socket = OSL_INVALID_SOCKET;
1195
1196
0
    sal_Int32 nRet=0;
1197
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1198
0
    pSocket->m_bIsInShutdown = true;
1199
1200
0
    if (pSocket->m_bIsAccepting)
1201
0
    {
1202
0
        union {
1203
0
            struct sockaddr aSockAddr;
1204
0
            struct sockaddr_in aSockAddrIn;
1205
0
        } s;
1206
0
        socklen_t nSockLen = sizeof(s.aSockAddr);
1207
1208
0
        nRet = getsockname(nFD, &s.aSockAddr, &nSockLen);
1209
0
        if (nRet < 0)
1210
0
        {
1211
0
            int nErrno = errno;
1212
0
            SAL_WARN( "sal.osl", "getsockname call failed: " << UnixErrnoString(nErrno) );
1213
0
        }
1214
1215
0
        if (s.aSockAddr.sa_family == AF_INET)
1216
0
        {
1217
0
            if (s.aSockAddrIn.sin_addr.s_addr == htonl(INADDR_ANY))
1218
0
            {
1219
0
                s.aSockAddrIn.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1220
0
            }
1221
1222
0
            int nConnFD = socket(AF_INET, SOCK_STREAM, 0);
1223
0
            if (nConnFD < 0)
1224
0
            {
1225
0
                int nErrno = errno;
1226
0
                SAL_WARN( "sal.osl", "socket call failed: " << UnixErrnoString(nErrno) );
1227
0
            }
1228
0
            else
1229
0
            {
1230
0
                nRet = connect(nConnFD, &s.aSockAddr, sizeof(s.aSockAddr));
1231
0
                if (nRet < 0)
1232
0
                {
1233
0
                    int nErrno = errno;
1234
0
                    SAL_WARN( "sal.osl", "connect call failed: " << UnixErrnoString(nErrno) );
1235
0
                }
1236
0
                close(nConnFD);
1237
0
            }
1238
0
        }
1239
0
        pSocket->m_bIsAccepting = false;
1240
0
    }
1241
0
#endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1242
1243
0
    nRet=close(nFD);
1244
0
    if (nRet != 0)
1245
0
    {
1246
0
        pSocket->m_nLastError=errno;
1247
0
        int nErrno = errno;
1248
0
        SAL_WARN( "sal.osl", "closeSocket close failed: " << UnixErrnoString(nErrno) );
1249
0
    }
1250
1251
0
    pSocket->m_Socket = OSL_INVALID_SOCKET;
1252
0
}
1253
1254
/* Note from function creator: I rely on the fact that oslSocketAddr and struct sockaddr
1255
   are the same! I don't like it very much but see no other easy way to conceal
1256
   the struct sockaddr from the eyes of the user. */
1257
oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
1258
0
{
1259
0
    socklen_t AddrLen;
1260
0
    struct sockaddr Addr;
1261
0
    oslSocketAddr  pAddr;
1262
1263
0
    if (pSocket == nullptr) /* ENOTSOCK */
1264
0
        return nullptr;
1265
1266
0
    AddrLen= sizeof(struct sockaddr);
1267
1268
0
    if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1269
0
        return nullptr;
1270
1271
0
    pAddr = createSocketAddrFromSystem( &Addr );
1272
0
    return pAddr;
1273
0
}
1274
1275
oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
1276
0
{
1277
0
    socklen_t AddrLen;
1278
0
    struct sockaddr Addr;
1279
1280
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1281
0
    if ( pSocket == nullptr )
1282
0
    {
1283
0
        return nullptr;
1284
0
    }
1285
1286
0
    pSocket->m_nLastError=0;
1287
0
    AddrLen= sizeof(struct sockaddr);
1288
1289
0
    if(getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
1290
0
    {
1291
0
        pSocket->m_nLastError=errno;
1292
0
        return nullptr;
1293
0
    }
1294
0
    return createSocketAddrFromSystem( &Addr );
1295
0
}
1296
1297
sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
1298
                             oslSocketAddr pAddr)
1299
0
{
1300
0
    int nRet;
1301
1302
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1303
0
    SAL_WARN_IF( !pAddr, "sal.osl", "undefined address" );
1304
0
    if ( pSocket == nullptr || pAddr == nullptr )
1305
0
    {
1306
0
        return false;
1307
0
    }
1308
1309
0
    pSocket->m_nLastError=0;
1310
1311
0
    nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
1312
1313
0
    if ( nRet == OSL_SOCKET_ERROR)
1314
0
    {
1315
0
        pSocket->m_nLastError=errno;
1316
0
        return false;
1317
0
    }
1318
1319
0
    return true;
1320
0
}
1321
1322
sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
1323
                           sal_Int32 MaxPendingConnections)
1324
0
{
1325
0
    int nRet;
1326
1327
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1328
0
    if ( pSocket == nullptr )
1329
0
    {
1330
0
        return false;
1331
0
    }
1332
1333
0
    pSocket->m_nLastError=0;
1334
1335
0
    nRet = listen(pSocket->m_Socket,
1336
0
                  MaxPendingConnections == -1 ?
1337
0
                  SOMAXCONN :
1338
0
                  MaxPendingConnections);
1339
0
    if ( nRet == OSL_SOCKET_ERROR)
1340
0
    {
1341
0
        pSocket->m_nLastError=errno;
1342
0
        return false;
1343
0
    }
1344
1345
0
    return true;
1346
0
}
1347
1348
oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
1349
                                    oslSocketAddr pAddr,
1350
                                    const TimeValue* pTimeout)
1351
0
{
1352
0
    int      ReadyHandles;
1353
1354
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1355
1356
0
    if ( pSocket == nullptr )
1357
0
    {
1358
0
        return osl_Socket_Error;
1359
0
    }
1360
1361
0
    pSocket->m_nLastError=0;
1362
1363
0
    if (osl_isNonBlockingMode(pSocket))
1364
0
    {
1365
0
        if (connect(pSocket->m_Socket,
1366
0
                    &(pAddr->m_sockaddr),
1367
0
                    sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1368
0
            return osl_Socket_Ok;
1369
1370
0
        if (errno == EWOULDBLOCK || errno == EINPROGRESS)
1371
0
        {
1372
0
            pSocket->m_nLastError=EINPROGRESS;
1373
0
            return osl_Socket_InProgress;
1374
0
        }
1375
1376
0
        pSocket->m_nLastError=errno;
1377
0
        int nErrno = errno;
1378
0
        SAL_WARN( "sal.osl", "connection failed: " << UnixErrnoString(nErrno) );
1379
0
        return osl_Socket_Error;
1380
0
    }
1381
1382
    /* set socket temporarily to non-blocking */
1383
0
    if( !osl_enableNonBlockingMode(pSocket, true) )
1384
0
        SAL_WARN( "sal.osl", "failed to enable non-blocking mode" );
1385
1386
    /* initiate connect */
1387
0
    if(connect(pSocket->m_Socket,
1388
0
               &(pAddr->m_sockaddr),
1389
0
               sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
1390
0
    {
1391
       /* immediate connection */
1392
0
        osl_enableNonBlockingMode(pSocket, false);
1393
1394
0
        return osl_Socket_Ok;
1395
0
    }
1396
1397
    /* really an error or just delayed? */
1398
0
    if (errno != EINPROGRESS)
1399
0
    {
1400
0
        pSocket->m_nLastError=errno;
1401
0
        int nErrno = errno;
1402
0
        SAL_WARN( "sal.osl", "connection failed: " << UnixErrnoString(nErrno) );
1403
1404
0
        osl_enableNonBlockingMode(pSocket, false);
1405
0
        return osl_Socket_Error;
1406
0
    }
1407
1408
    /* prepare poll set for socket  */
1409
0
    pollfd Set = {pSocket->m_Socket, POLLPRI | POLLOUT, 0};
1410
1411
    /* poll */
1412
0
    ReadyHandles= poll(&Set, 1,
1413
0
                         pTimeout ? convertToMs(pTimeout) : -1);
1414
1415
0
    if (ReadyHandles > 0)  /* connected */
1416
0
    {
1417
0
        if ( (Set.revents & POLLOUT) != 0 )
1418
0
        {
1419
0
            int nErrorCode = 0;
1420
0
            socklen_t nErrorSize = sizeof( nErrorCode );
1421
1422
0
            int nSockOpt;
1423
1424
0
            nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
1425
0
                                    &nErrorCode, &nErrorSize );
1426
0
            if ( (nSockOpt == 0) && (nErrorCode == 0))
1427
0
            {
1428
0
                osl_enableNonBlockingMode(pSocket, false);
1429
0
                return osl_Socket_Ok;
1430
0
            }
1431
0
            else
1432
0
            {
1433
0
                pSocket->m_nLastError = (nSockOpt == 0) ? nErrorCode : errno;
1434
0
                return osl_Socket_Error;
1435
0
            }
1436
0
        }
1437
0
        else
1438
0
        {
1439
0
            return osl_Socket_Error;
1440
0
        }
1441
0
    }
1442
0
    else if (ReadyHandles < 0)  /* error */
1443
0
    {
1444
0
        if (errno == EBADF) /* most probably interrupted by close() */
1445
0
        {
1446
            /* do not access pSockImpl because it is about to be or */
1447
            /* already destroyed */
1448
0
            return osl_Socket_Interrupted;
1449
0
        }
1450
0
        pSocket->m_nLastError=errno;
1451
0
        return osl_Socket_Error;
1452
0
    }
1453
0
    else    /* timeout */
1454
0
    {
1455
0
        pSocket->m_nLastError=errno;
1456
0
        return osl_Socket_TimedOut;
1457
0
    }
1458
0
}
1459
1460
oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
1461
                        oslSocketAddr* ppAddr)
1462
0
{
1463
0
    struct sockaddr Addr;
1464
0
    int Connection, Flags;
1465
0
    oslSocket pConnectionSockImpl;
1466
1467
0
    socklen_t AddrLen = sizeof(struct sockaddr);
1468
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1469
0
    if ( pSocket == nullptr )
1470
0
    {
1471
0
        return nullptr;
1472
0
    }
1473
1474
0
    pSocket->m_nLastError=0;
1475
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1476
0
    pSocket->m_bIsAccepting = true;
1477
0
#endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1478
1479
0
    if( ppAddr && *ppAddr )
1480
0
    {
1481
0
        osl_destroySocketAddr( *ppAddr );
1482
0
        *ppAddr = nullptr;
1483
0
    }
1484
1485
    /* prevent Linux EINTR behaviour */
1486
0
    do
1487
0
    {
1488
0
        Connection = accept(pSocket->m_Socket, &Addr, &AddrLen);
1489
0
    } while (Connection == -1 && errno == EINTR);
1490
1491
    /* accept failed? */
1492
0
    if( Connection == OSL_SOCKET_ERROR )
1493
0
    {
1494
0
        pSocket->m_nLastError=errno;
1495
0
        int nErrno = errno;
1496
0
        SAL_WARN( "sal.osl", "accept connection failed: " << UnixErrnoString(nErrno) );
1497
1498
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1499
0
        pSocket->m_bIsAccepting = false;
1500
0
#endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1501
0
        return nullptr;
1502
0
    }
1503
1504
0
    assert(AddrLen == sizeof(struct sockaddr));
1505
1506
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1507
0
    if ( pSocket->m_bIsInShutdown )
1508
0
    {
1509
0
        close(Connection);
1510
0
        SAL_WARN( "sal.osl", "close while accept" );
1511
0
        return nullptr;
1512
0
    }
1513
0
#endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1514
1515
0
    if(ppAddr)
1516
0
    {
1517
0
        *ppAddr= createSocketAddrFromSystem(&Addr);
1518
0
    }
1519
1520
    /* alloc memory */
1521
0
    pConnectionSockImpl= createSocketImpl();
1522
1523
    /* set close-on-exec flag */
1524
0
    if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
1525
0
    {
1526
0
        Flags |= FD_CLOEXEC;
1527
0
        if (fcntl(Connection, F_SETFD, Flags) == -1)
1528
0
        {
1529
0
            pSocket->m_nLastError=errno;
1530
0
            int nErrno = errno;
1531
0
            SAL_WARN( "sal.osl", "fcntl failed: " << UnixErrnoString(nErrno) );
1532
0
        }
1533
1534
0
    }
1535
1536
0
    pConnectionSockImpl->m_Socket           = Connection;
1537
0
    pConnectionSockImpl->m_nLastError       = 0;
1538
0
#if defined(CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT)
1539
0
    pConnectionSockImpl->m_bIsAccepting     = false;
1540
1541
0
    pSocket->m_bIsAccepting = false;
1542
0
#endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
1543
0
    return pConnectionSockImpl;
1544
0
}
1545
1546
sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
1547
                          void* pBuffer,
1548
                          sal_uInt32 BytesToRead,
1549
                          oslSocketMsgFlag Flag)
1550
0
{
1551
0
    int nRead;
1552
1553
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1554
0
    if ( pSocket == nullptr )
1555
0
    {
1556
0
        return -1;
1557
0
    }
1558
1559
0
    pSocket->m_nLastError=0;
1560
1561
0
    do
1562
0
    {
1563
0
        nRead =  recv(pSocket->m_Socket,
1564
0
                      pBuffer,
1565
0
                      BytesToRead,
1566
0
                      MSG_FLAG_TO_NATIVE(Flag));
1567
0
    } while ( nRead < 0 && errno == EINTR );
1568
1569
0
    if ( nRead < 0 )
1570
0
    {
1571
0
        pSocket->m_nLastError=errno;
1572
0
        int nErrno = errno;
1573
0
        SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: " << UnixErrnoString(nErrno) );
1574
0
    }
1575
0
    else if ( nRead == 0 )
1576
0
    {
1577
0
        SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: EOL" );
1578
0
    }
1579
1580
0
    return nRead;
1581
0
}
1582
1583
sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
1584
                              oslSocketAddr pSenderAddr,
1585
                              void* pBuffer,
1586
                              sal_uInt32 BufferSize,
1587
                              oslSocketMsgFlag Flag)
1588
0
{
1589
0
    int nRead;
1590
0
    struct sockaddr *pSystemSockAddr = nullptr;
1591
0
    socklen_t AddrLen = 0;
1592
0
    if( pSenderAddr )
1593
0
    {
1594
0
        AddrLen = sizeof( struct sockaddr );
1595
0
        pSystemSockAddr = &(pSenderAddr->m_sockaddr);
1596
0
    }
1597
1598
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1599
0
    if ( pSocket == nullptr )
1600
0
    {
1601
0
        return -1;
1602
0
    }
1603
1604
0
    pSocket->m_nLastError=0;
1605
1606
0
    nRead = recvfrom(pSocket->m_Socket,
1607
0
                     pBuffer,
1608
0
                     BufferSize,
1609
0
                     MSG_FLAG_TO_NATIVE(Flag),
1610
0
                     pSystemSockAddr,
1611
0
                     &AddrLen);
1612
1613
0
    if ( nRead < 0 )
1614
0
    {
1615
0
        pSocket->m_nLastError=errno;
1616
0
        int nErrno = errno;
1617
0
        SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: " << UnixErrnoString(nErrno) );
1618
0
    }
1619
0
    else if ( nRead == 0 )
1620
0
    {
1621
0
        SAL_WARN( "sal.osl", "receive socket [" << nRead << "] failed: EOL" );
1622
0
    }
1623
1624
0
    return nRead;
1625
0
}
1626
1627
sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
1628
                       const void* pBuffer,
1629
                       sal_uInt32 BytesToSend,
1630
                       oslSocketMsgFlag Flag)
1631
0
{
1632
0
    int nWritten;
1633
1634
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1635
0
    if ( pSocket == nullptr )
1636
0
    {
1637
0
        return -1;
1638
0
    }
1639
1640
0
    pSocket->m_nLastError=0;
1641
1642
0
    do
1643
0
    {
1644
0
        nWritten = send(pSocket->m_Socket,
1645
0
                        pBuffer,
1646
0
                        BytesToSend,
1647
0
                        MSG_FLAG_TO_NATIVE(Flag));
1648
0
    } while ( nWritten < 0 && errno == EINTR );
1649
1650
0
    if ( nWritten < 0 )
1651
0
    {
1652
0
        pSocket->m_nLastError=errno;
1653
0
        int nErrno = errno;
1654
0
        SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: " << UnixErrnoString(nErrno) );
1655
0
    }
1656
0
    else if ( nWritten == 0 )
1657
0
    {
1658
0
        SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: EOL" );
1659
0
    }
1660
1661
0
    return nWritten;
1662
0
}
1663
1664
sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
1665
                         oslSocketAddr ReceiverAddr,
1666
                         const void* pBuffer,
1667
                         sal_uInt32 BytesToSend,
1668
                         oslSocketMsgFlag Flag)
1669
0
{
1670
0
    int nWritten;
1671
1672
0
    struct sockaddr *pSystemSockAddr = nullptr;
1673
0
    int AddrLen = 0;
1674
0
    if( ReceiverAddr )
1675
0
    {
1676
0
        pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
1677
0
        AddrLen = sizeof( struct sockaddr );
1678
0
    }
1679
1680
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1681
0
    if ( pSocket == nullptr )
1682
0
    {
1683
0
        return -1;
1684
0
    }
1685
1686
0
    pSocket->m_nLastError=0;
1687
1688
    /* ReceiverAddr might be 0 when used on a connected socket. */
1689
    /* Then sendto should behave like send. */
1690
1691
0
    nWritten = sendto(pSocket->m_Socket,
1692
0
                      pBuffer,
1693
0
                      BytesToSend,
1694
0
                      MSG_FLAG_TO_NATIVE(Flag),
1695
0
                      pSystemSockAddr,
1696
0
                      AddrLen);
1697
1698
0
    if ( nWritten < 0 )
1699
0
    {
1700
0
        pSocket->m_nLastError=errno;
1701
0
        int nErrno = errno;
1702
0
        SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: " << UnixErrnoString(nErrno) );
1703
0
    }
1704
0
    else if ( nWritten == 0 )
1705
0
    {
1706
0
        SAL_WARN( "sal.osl", "send socket [" << nWritten << "] failed: EOL" );
1707
0
    }
1708
1709
0
    return nWritten;
1710
0
}
1711
1712
sal_Int32 SAL_CALL osl_readSocket (
1713
    oslSocket pSocket, void *pBuffer, sal_Int32 n )
1714
0
{
1715
0
    sal_uInt8 * Ptr = static_cast<sal_uInt8 *>(pBuffer);
1716
0
    sal_uInt32 BytesRead= 0;
1717
0
    sal_uInt32 BytesToRead= n;
1718
1719
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1720
1721
    /* loop until all desired bytes were read or an error occurred */
1722
0
    while (BytesToRead > 0)
1723
0
    {
1724
0
        sal_Int32 RetVal;
1725
0
        RetVal= osl_receiveSocket(pSocket,
1726
0
                                   Ptr,
1727
0
                                   BytesToRead,
1728
0
                                   osl_Socket_MsgNormal);
1729
1730
        /* error occurred? */
1731
0
        if(RetVal <= 0)
1732
0
        {
1733
0
            break;
1734
0
        }
1735
1736
0
        BytesToRead -= RetVal;
1737
0
        BytesRead += RetVal;
1738
0
        Ptr += RetVal;
1739
0
    }
1740
1741
0
    return BytesRead;
1742
0
}
1743
1744
sal_Int32 SAL_CALL osl_writeSocket(
1745
    oslSocket pSocket, const void *pBuffer, sal_Int32 n )
1746
0
{
1747
    /* loop until all desired bytes were send or an error occurred */
1748
0
    sal_uInt32 BytesSend= 0;
1749
0
    sal_uInt32 BytesToSend= n;
1750
0
    sal_uInt8 const *Ptr = static_cast<sal_uInt8 const *>(pBuffer);
1751
1752
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1753
1754
0
    while (BytesToSend > 0)
1755
0
    {
1756
0
        sal_Int32 RetVal;
1757
1758
0
        RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
1759
1760
        /* error occurred? */
1761
0
        if(RetVal <= 0)
1762
0
        {
1763
0
            break;
1764
0
        }
1765
1766
0
        BytesToSend -= RetVal;
1767
0
        BytesSend += RetVal;
1768
0
        Ptr += RetVal;
1769
1770
0
    }
1771
0
    return BytesSend;
1772
0
}
1773
1774
static bool socket_poll (
1775
    oslSocket        pSocket,
1776
    const TimeValue* pTimeout,
1777
    short            nEvent)
1778
0
{
1779
0
    struct pollfd fds;
1780
0
    int           timeout;
1781
0
    int           result;
1782
1783
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1784
0
    if (pSocket == nullptr)
1785
0
      return false; /* EINVAL */
1786
1787
0
    pSocket->m_nLastError = 0;
1788
1789
0
    fds.fd      = pSocket->m_Socket;
1790
0
    fds.events  = nEvent;
1791
0
    fds.revents = 0;
1792
1793
0
    timeout = -1;
1794
0
    if (pTimeout)
1795
0
    {
1796
0
        timeout  = convertToMs(pTimeout);
1797
0
    }
1798
1799
0
    result = poll (&fds, 1, timeout);
1800
0
    if (result < 0)
1801
0
    {
1802
0
        pSocket->m_nLastError = errno;
1803
0
        int nErrno = errno;
1804
0
        SAL_WARN( "sal.osl", "poll failed: " << UnixErrnoString(nErrno) );
1805
0
        return false;
1806
0
    }
1807
0
    if (result == 0)
1808
0
    {
1809
        /* Timeout */
1810
0
        return false;
1811
0
    }
1812
1813
0
    return ((fds.revents & nEvent) == nEvent);
1814
0
}
1815
1816
sal_Bool SAL_CALL osl_isReceiveReady (
1817
    oslSocket pSocket, const TimeValue* pTimeout)
1818
0
{
1819
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1820
0
    if (pSocket == nullptr)
1821
0
    {
1822
        /* ENOTSOCK */
1823
0
        return false;
1824
0
    }
1825
1826
0
    return socket_poll (pSocket, pTimeout, POLLIN);
1827
0
}
1828
1829
sal_Bool SAL_CALL osl_isSendReady (
1830
    oslSocket pSocket, const TimeValue* pTimeout)
1831
0
{
1832
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1833
0
    if (pSocket == nullptr)
1834
0
    {
1835
        /* ENOTSOCK */
1836
0
        return false;
1837
0
    }
1838
1839
0
    return socket_poll (pSocket, pTimeout, POLLOUT);
1840
0
}
1841
1842
sal_Bool SAL_CALL osl_isExceptionPending (
1843
    oslSocket pSocket, const TimeValue* pTimeout)
1844
0
{
1845
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1846
0
    if (pSocket == nullptr)
1847
0
    {
1848
        /* ENOTSOCK */
1849
0
        return false;
1850
0
    }
1851
1852
0
    return socket_poll (pSocket, pTimeout, POLLPRI);
1853
0
}
1854
1855
sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
1856
                           oslSocketDirection Direction)
1857
0
{
1858
0
    int nRet;
1859
1860
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1861
0
    if ( pSocket == nullptr )
1862
0
    {
1863
0
        return false;
1864
0
    }
1865
1866
0
    pSocket->m_nLastError=0;
1867
1868
0
    nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
1869
0
    if (nRet != 0 )
1870
0
    {
1871
0
        pSocket->m_nLastError=errno;
1872
0
        int nErrno = errno;
1873
0
        SAL_WARN( "sal.osl", "shutdown failed: " << UnixErrnoString(nErrno) );
1874
0
    }
1875
0
    return (nRet==0);
1876
0
}
1877
1878
sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
1879
                            oslSocketOptionLevel    Level,
1880
                            oslSocketOption         Option,
1881
                            void*                   pBuffer,
1882
                            sal_uInt32                  BufferLen)
1883
0
{
1884
0
    socklen_t nOptLen = static_cast<socklen_t>(BufferLen);
1885
1886
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1887
0
    if ( pSocket == nullptr )
1888
0
    {
1889
0
        return -1;
1890
0
    }
1891
1892
0
    pSocket->m_nLastError=0;
1893
1894
0
    if(getsockopt(pSocket->m_Socket,
1895
0
                  OPTION_LEVEL_TO_NATIVE(Level),
1896
0
                  OPTION_TO_NATIVE(Option),
1897
0
                  pBuffer,
1898
0
                  &nOptLen) == -1)
1899
0
    {
1900
0
        pSocket->m_nLastError=errno;
1901
0
        return -1;
1902
0
    }
1903
1904
0
    return nOptLen;
1905
0
}
1906
1907
sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
1908
                            oslSocketOptionLevel    Level,
1909
                            oslSocketOption         Option,
1910
                            void*                   pBuffer,
1911
                            sal_uInt32                  BufferLen)
1912
0
{
1913
0
    int nRet;
1914
1915
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1916
0
    if ( pSocket == nullptr )
1917
0
    {
1918
0
        return false;
1919
0
    }
1920
1921
0
    pSocket->m_nLastError=0;
1922
1923
0
    nRet = setsockopt(pSocket->m_Socket,
1924
0
                      OPTION_LEVEL_TO_NATIVE(Level),
1925
0
                      OPTION_TO_NATIVE(Option),
1926
0
                      pBuffer,
1927
0
                      BufferLen);
1928
1929
0
    if ( nRet < 0 )
1930
0
    {
1931
0
        pSocket->m_nLastError=errno;
1932
0
        return false;
1933
0
    }
1934
1935
0
    return true;
1936
0
}
1937
1938
sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
1939
                                  sal_Bool On)
1940
0
{
1941
0
    int flags;
1942
0
    int nRet;
1943
1944
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1945
0
    if ( pSocket == nullptr )
1946
0
    {
1947
0
        return false;
1948
0
    }
1949
1950
0
    pSocket->m_nLastError=0;
1951
1952
0
    flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
1953
1954
0
    if (On)
1955
0
        flags |= O_NONBLOCK;
1956
0
    else
1957
0
        flags &= ~(O_NONBLOCK);
1958
1959
0
    nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
1960
1961
0
    if  ( nRet < 0 )
1962
0
    {
1963
0
        pSocket->m_nLastError=errno;
1964
0
        return false;
1965
0
    }
1966
1967
0
    return true;
1968
0
}
1969
1970
sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
1971
0
{
1972
0
    int flags;
1973
1974
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1975
0
    if ( pSocket == nullptr )
1976
0
    {
1977
0
        return false;
1978
0
    }
1979
1980
0
    pSocket->m_nLastError=0;
1981
1982
0
    flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
1983
1984
0
    if (flags == -1 || !(flags & O_NONBLOCK))
1985
0
        return false;
1986
1987
0
    return true;
1988
0
}
1989
1990
oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
1991
0
{
1992
0
    int Type=0;
1993
0
    socklen_t TypeSize= sizeof(Type);
1994
1995
0
    SAL_WARN_IF( !pSocket, "sal.osl", "undefined socket" );
1996
0
    if ( pSocket == nullptr )
1997
0
    {
1998
0
        return osl_Socket_TypeInvalid;
1999
0
    }
2000
2001
0
    pSocket->m_nLastError=0;
2002
2003
0
    if(getsockopt(pSocket->m_Socket,
2004
0
                  OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
2005
0
                  OPTION_TO_NATIVE(osl_Socket_OptionType),
2006
0
                  &Type,
2007
0
                  &TypeSize) == -1)
2008
0
    {
2009
        /* error */
2010
0
        pSocket->m_nLastError=errno;
2011
0
        return osl_Socket_TypeInvalid;
2012
0
    }
2013
2014
0
    return TYPE_FROM_NATIVE(Type);
2015
2016
0
}
2017
2018
void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
2019
0
{
2020
0
    char pszError[1024];
2021
2022
0
    pszError[0] = '\0';
2023
2024
0
    osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
2025
2026
0
    rtl_uString_newFromAscii(ustrError,pszError);
2027
0
}
2028
2029
void osl_psz_getLastSocketErrorDescription(oslSocket pSocket, char* pBuffer, sal_uInt32 BufferSize)
2030
0
{
2031
    /* make sure pBuffer will be a zero-terminated string even when strncpy has to cut */
2032
0
    pBuffer[BufferSize-1]= '\0';
2033
2034
0
    if ( pSocket == nullptr )
2035
0
    {
2036
0
        strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
2037
0
        return;
2038
0
    }
2039
2040
0
    strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
2041
0
}
2042
2043
oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
2044
0
{
2045
0
    if ( pSocket == nullptr )
2046
0
    {
2047
0
        return ERROR_FROM_NATIVE(EINVAL);
2048
0
    }
2049
2050
0
    return ERROR_FROM_NATIVE(pSocket->m_nLastError);
2051
0
}
2052
2053
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */