/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: */ |