1 //===-- Socket.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Host/Socket.h"
11 
12 #include "lldb/Core/Log.h"
13 #include "lldb/Core/RegularExpression.h"
14 #include "lldb/Host/Config.h"
15 #include "lldb/Host/FileSystem.h"
16 #include "lldb/Host/Host.h"
17 #include "lldb/Host/SocketAddress.h"
18 #include "lldb/Host/StringConvert.h"
19 #include "lldb/Host/TimeValue.h"
20 
21 #ifdef __ANDROID_NDK__
22 #include <linux/tcp.h>
23 #include <bits/error_constants.h>
24 #include <asm-generic/errno-base.h>
25 #include <errno.h>
26 #include <arpa/inet.h>
27 #endif
28 
29 #ifndef LLDB_DISABLE_POSIX
30 #include <arpa/inet.h>
31 #include <netdb.h>
32 #include <netinet/in.h>
33 #include <netinet/tcp.h>
34 #include <sys/socket.h>
35 #include <sys/un.h>
36 #endif
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 
41 #if defined(_WIN32)
42 typedef const char * set_socket_option_arg_type;
43 typedef char * get_socket_option_arg_type;
44 const NativeSocket Socket::kInvalidSocketValue = INVALID_SOCKET;
45 #else // #if defined(_WIN32)
46 typedef const void * set_socket_option_arg_type;
47 typedef void * get_socket_option_arg_type;
48 const NativeSocket Socket::kInvalidSocketValue = -1;
49 #endif // #if defined(_WIN32)
50 
51 #ifdef __ANDROID__
52 // Android does not have SUN_LEN
53 #ifndef SUN_LEN
54 #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
55 #endif
56 #endif // #ifdef __ANDROID__
57 
58 namespace {
59 
60 NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit)
61 {
62     auto socketType = type;
63 #ifdef SOCK_CLOEXEC
64     if (!child_processes_inherit) {
65         socketType |= SOCK_CLOEXEC;
66     }
67 #endif
68     return ::socket (domain, socketType, protocol);
69 }
70 
71 NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit)
72 {
73 #ifdef SOCK_CLOEXEC
74     int flags = 0;
75     if (!child_processes_inherit) {
76         flags |= SOCK_CLOEXEC;
77     }
78     return ::accept4 (sockfd, addr, addrlen, flags);
79 #else
80     return ::accept (sockfd, addr, addrlen);
81 #endif
82 }
83 
84 void SetLastError(Error &error)
85 {
86 #if defined(_WIN32)
87     error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32);
88 #else
89     error.SetErrorToErrno();
90 #endif
91 }
92 
93 bool IsInterrupted()
94 {
95 #if defined(_WIN32)
96     return ::WSAGetLastError() == WSAEINTR;
97 #else
98     return errno == EINTR;
99 #endif
100 }
101 
102 }
103 
104 Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close)
105     : IOObject(eFDTypeSocket, should_close)
106     , m_protocol(protocol)
107     , m_socket(socket)
108 {
109 
110 }
111 
112 Socket::~Socket()
113 {
114     Close();
115 }
116 
117 Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket)
118 {
119     // Store the result in a unique_ptr in case we error out, the memory will get correctly freed.
120     std::unique_ptr<Socket> final_socket;
121     NativeSocket sock = kInvalidSocketValue;
122     Error error;
123 
124     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
125     if (log)
126         log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data());
127 
128     std::string host_str;
129     std::string port_str;
130     int32_t port = INT32_MIN;
131     if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
132         return error;
133 
134     // Create the socket
135     sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit);
136     if (sock == kInvalidSocketValue)
137     {
138         SetLastError (error);
139         return error;
140     }
141 
142     // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to
143     // be the owner.
144     final_socket.reset(new Socket(sock, ProtocolTcp, true));
145 
146     // Enable local address reuse
147     final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
148 
149     struct sockaddr_in sa;
150     ::memset (&sa, 0, sizeof (sa));
151     sa.sin_family = AF_INET;
152     sa.sin_port = htons (port);
153 
154     int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
155 
156     if (inet_pton_result <= 0)
157     {
158         struct hostent *host_entry = gethostbyname (host_str.c_str());
159         if (host_entry)
160             host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
161         inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
162         if (inet_pton_result <= 0)
163         {
164             if (inet_pton_result == -1)
165                 SetLastError(error);
166             else
167                 error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str());
168 
169             return error;
170         }
171     }
172 
173     if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa)))
174     {
175         SetLastError (error);
176         return error;
177     }
178 
179     // Keep our TCP packets coming without any delays.
180     final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1);
181     error.Clear();
182     socket = final_socket.release();
183     return error;
184 }
185 
186 Error Socket::TcpListen(
187     llvm::StringRef host_and_port,
188     bool child_processes_inherit,
189     Socket *&socket,
190     Predicate<uint16_t>* predicate,
191     int backlog)
192 {
193     std::unique_ptr<Socket> listen_socket;
194     NativeSocket listen_sock = kInvalidSocketValue;
195     Error error;
196 
197     const sa_family_t family = AF_INET;
198     const int socktype = SOCK_STREAM;
199     const int protocol = IPPROTO_TCP;
200     listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit);
201     if (listen_sock == kInvalidSocketValue)
202     {
203         SetLastError (error);
204         return error;
205     }
206 
207     listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true));
208 
209     // enable local address reuse
210     listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1);
211 
212     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
213     if (log)
214         log->Printf ("Socket::TcpListen (%s)", host_and_port.data());
215 
216     std::string host_str;
217     std::string port_str;
218     int32_t port = INT32_MIN;
219     if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
220         return error;
221 
222     SocketAddress anyaddr;
223     if (anyaddr.SetToAnyAddress (family, port))
224     {
225         int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength());
226         if (err == -1)
227         {
228             SetLastError (error);
229             return error;
230         }
231 
232         err = ::listen (listen_sock, backlog);
233         if (err == -1)
234         {
235             SetLastError (error);
236             return error;
237         }
238 
239         // We were asked to listen on port zero which means we
240         // must now read the actual port that was given to us
241         // as port zero is a special code for "find an open port
242         // for me".
243         if (port == 0)
244             port = listen_socket->GetLocalPortNumber();
245 
246         // Set the port predicate since when doing a listen://<host>:<port>
247         // it often needs to accept the incoming connection which is a blocking
248         // system call. Allowing access to the bound port using a predicate allows
249         // us to wait for the port predicate to be set to a non-zero value from
250         // another thread in an efficient manor.
251         if (predicate)
252             predicate->SetValue (port, eBroadcastAlways);
253 
254         socket = listen_socket.release();
255     }
256 
257     return error;
258 }
259 
260 Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket)
261 {
262     Error error;
263     std::string host_str;
264     std::string port_str;
265     int32_t port;
266     if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error))
267         return error;
268 
269     const sa_family_t family = AF_INET;
270     const int socktype = SOCK_STREAM;
271     const int protocol = IPPROTO_TCP;
272     SocketAddress listen_addr;
273     if (host_str.empty())
274         listen_addr.SetToLocalhost(family, port);
275     else if (host_str.compare("*") == 0)
276         listen_addr.SetToAnyAddress(family, port);
277     else
278     {
279         if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol))
280         {
281             error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str());
282             return error;
283         }
284     }
285 
286     bool accept_connection = false;
287     std::unique_ptr<Socket> accepted_socket;
288 
289     // Loop until we are happy with our connection
290     while (!accept_connection)
291     {
292         struct sockaddr_in accept_addr;
293         ::memset (&accept_addr, 0, sizeof accept_addr);
294 #if !(defined (__linux__) || defined(_WIN32))
295         accept_addr.sin_len = sizeof accept_addr;
296 #endif
297         socklen_t accept_addr_len = sizeof accept_addr;
298 
299         int sock = Accept (this->GetNativeSocket(),
300                            (struct sockaddr *)&accept_addr,
301                            &accept_addr_len,
302                            child_processes_inherit);
303 
304         if (sock == kInvalidSocketValue)
305         {
306             SetLastError (error);
307             break;
308         }
309 
310         bool is_same_addr = true;
311 #if !(defined(__linux__) || (defined(_WIN32)))
312         is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
313 #endif
314         if (is_same_addr)
315             is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr);
316 
317         if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY))
318         {
319             accept_connection = true;
320             // Since both sockets have the same descriptor, arbitrarily choose the send
321             // socket to be the owner.
322             accepted_socket.reset(new Socket(sock, ProtocolTcp, true));
323         }
324         else
325         {
326             const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
327             const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
328             ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
329                         accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
330                         listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
331             accepted_socket.reset();
332         }
333     }
334 
335     if (!accepted_socket)
336         return error;
337 
338     // Keep our TCP packets coming without any delays.
339     accepted_socket->SetOption (IPPROTO_TCP, TCP_NODELAY, 1);
340     error.Clear();
341     socket = accepted_socket.release();
342     return error;
343 
344 }
345 
346 Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket)
347 {
348     std::unique_ptr<Socket> final_send_socket;
349     std::unique_ptr<Socket> final_recv_socket;
350     NativeSocket final_send_fd = kInvalidSocketValue;
351     NativeSocket final_recv_fd = kInvalidSocketValue;
352 
353     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
354     if (log)
355         log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data());
356 
357     Error error;
358     std::string host_str;
359     std::string port_str;
360     int32_t port = INT32_MIN;
361     if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error))
362         return error;
363 
364     // Setup the receiving end of the UDP connection on this localhost
365     // on port zero. After we bind to port zero we can read the port.
366     final_recv_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit);
367     if (final_recv_fd == kInvalidSocketValue)
368     {
369         // Socket creation failed...
370         SetLastError (error);
371     }
372     else
373     {
374         final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true));
375 
376         // Socket was created, now lets bind to the requested port
377         SocketAddress addr;
378         addr.SetToAnyAddress (AF_INET, 0);
379 
380         if (::bind (final_recv_fd, addr, addr.GetLength()) == -1)
381         {
382             // Bind failed...
383             SetLastError (error);
384         }
385     }
386 
387     assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid()));
388     if (error.Fail())
389         return error;
390 
391     // At this point we have setup the receive port, now we need to
392     // setup the UDP send socket
393 
394     struct addrinfo hints;
395     struct addrinfo *service_info_list = NULL;
396 
397     ::memset (&hints, 0, sizeof(hints));
398     hints.ai_family = AF_INET;
399     hints.ai_socktype = SOCK_DGRAM;
400     int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list);
401     if (err != 0)
402     {
403         error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)",
404                                        host_str.c_str(),
405                                        port_str.c_str(),
406                                        err,
407                                        gai_strerror(err));
408         return error;
409     }
410 
411     for (struct addrinfo *service_info_ptr = service_info_list;
412          service_info_ptr != NULL;
413          service_info_ptr = service_info_ptr->ai_next)
414     {
415         final_send_fd = ::CreateSocket (service_info_ptr->ai_family,
416                                         service_info_ptr->ai_socktype,
417                                         service_info_ptr->ai_protocol,
418                                         child_processes_inherit);
419 
420         if (final_send_fd != kInvalidSocketValue)
421         {
422             final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true));
423             final_send_socket->m_udp_send_sockaddr = service_info_ptr;
424             break;
425         }
426         else
427             continue;
428     }
429 
430     :: freeaddrinfo (service_info_list);
431 
432     if (final_send_fd == kInvalidSocketValue)
433     {
434         SetLastError (error);
435         return error;
436     }
437 
438     send_socket = final_send_socket.release();
439     recv_socket = final_recv_socket.release();
440     error.Clear();
441     return error;
442 }
443 
444 Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
445 {
446     Error error;
447 #ifndef LLDB_DISABLE_POSIX
448     std::unique_ptr<Socket> final_socket;
449 
450     // Open the socket that was passed in as an option
451     struct sockaddr_un saddr_un;
452     int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit);
453     if (fd == kInvalidSocketValue)
454     {
455         SetLastError (error);
456         return error;
457     }
458 
459     final_socket.reset(new Socket(fd, ProtocolUnixDomain, true));
460 
461     saddr_un.sun_family = AF_UNIX;
462     ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
463     saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
464 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
465     saddr_un.sun_len = SUN_LEN (&saddr_un);
466 #endif
467 
468     if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
469     {
470         SetLastError (error);
471         return error;
472     }
473 
474     socket = final_socket.release();
475 #else
476     error.SetErrorString("Unix domain sockets are not supported on this platform.");
477 #endif
478     return error;
479 }
480 
481 Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket)
482 {
483     Error error;
484 #ifndef LLDB_DISABLE_POSIX
485     struct sockaddr_un saddr_un;
486     std::unique_ptr<Socket> listen_socket;
487     std::unique_ptr<Socket> final_socket;
488     NativeSocket listen_fd = kInvalidSocketValue;
489     NativeSocket socket_fd = kInvalidSocketValue;
490 
491     listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit);
492     if (listen_fd == kInvalidSocketValue)
493     {
494         SetLastError (error);
495         return error;
496     }
497 
498     listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true));
499 
500     saddr_un.sun_family = AF_UNIX;
501     ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1);
502     saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
503 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
504     saddr_un.sun_len = SUN_LEN (&saddr_un);
505 #endif
506 
507     FileSystem::Unlink(FileSpec{name, true});
508     bool success = false;
509     if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
510     {
511         if (::listen (listen_fd, 5) == 0)
512         {
513             socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit);
514             if (socket_fd > 0)
515             {
516                 final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true));
517                 success = true;
518             }
519         }
520     }
521 
522     if (!success)
523     {
524         SetLastError (error);
525         return error;
526     }
527     // We are done with the listen port
528     listen_socket.reset();
529 
530     socket = final_socket.release();
531 #else
532     error.SetErrorString("Unix domain sockets are not supported on this platform.");
533 #endif
534     return error;
535 }
536 
537 bool
538 Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
539                           std::string &host_str,
540                           std::string &port_str,
541                           int32_t& port,
542                           Error *error_ptr)
543 {
544     static RegularExpression g_regex ("([^:]+):([0-9]+)");
545     RegularExpression::Match regex_match(2);
546     if (g_regex.Execute (host_and_port.data(), &regex_match))
547     {
548         if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) &&
549             regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str))
550         {
551             bool ok = false;
552             port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok);
553             if (ok && port < UINT16_MAX)
554             {
555                 if (error_ptr)
556                     error_ptr->Clear();
557                 return true;
558             }
559             // port is too large
560             if (error_ptr)
561                 error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
562             return false;
563         }
564     }
565 
566     // If this was unsuccessful, then check if it's simply a signed 32-bit integer, representing
567     // a port with an empty host.
568     host_str.clear();
569     port_str.clear();
570     bool ok = false;
571     port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok);
572     if (ok && port < UINT16_MAX)
573     {
574         port_str = host_and_port;
575         if (error_ptr)
576             error_ptr->Clear();
577         return true;
578     }
579 
580     if (error_ptr)
581         error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data());
582     return false;
583 }
584 
585 IOObject::WaitableHandle Socket::GetWaitableHandle()
586 {
587     // TODO: On Windows, use WSAEventSelect
588     return m_socket;
589 }
590 
591 Error Socket::Read (void *buf, size_t &num_bytes)
592 {
593     Error error;
594     int bytes_received = 0;
595     do
596     {
597         bytes_received = ::recv (m_socket, static_cast<char *>(buf), num_bytes, 0);
598     } while (bytes_received < 0 && IsInterrupted ());
599 
600     if (bytes_received < 0)
601     {
602         SetLastError (error);
603         num_bytes = 0;
604     }
605     else
606         num_bytes = bytes_received;
607 
608     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION));
609     if (log)
610     {
611         log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
612                      static_cast<void*>(this),
613                      static_cast<uint64_t>(m_socket),
614                      buf,
615                      static_cast<uint64_t>(num_bytes),
616                      static_cast<int64_t>(bytes_received),
617                      error.AsCString());
618     }
619 
620     return error;
621 }
622 
623 Error Socket::Write (const void *buf, size_t &num_bytes)
624 {
625     Error error;
626     int bytes_sent = 0;
627     do
628     {
629         if (m_protocol == ProtocolUdp)
630         {
631             bytes_sent = ::sendto (m_socket,
632                                     static_cast<const char*>(buf),
633                                     num_bytes,
634                                     0,
635                                     m_udp_send_sockaddr,
636                                     m_udp_send_sockaddr.GetLength());
637         }
638         else
639             bytes_sent = ::send (m_socket, static_cast<const char *>(buf), num_bytes, 0);
640     } while (bytes_sent < 0 && IsInterrupted ());
641 
642     if (bytes_sent < 0)
643     {
644         SetLastError (error);
645         num_bytes = 0;
646     }
647     else
648         num_bytes = bytes_sent;
649 
650     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
651     if (log)
652     {
653         log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)",
654                         static_cast<void*>(this),
655                         static_cast<uint64_t>(m_socket),
656                         buf,
657                         static_cast<uint64_t>(num_bytes),
658                         static_cast<int64_t>(bytes_sent),
659                         error.AsCString());
660     }
661 
662     return error;
663 }
664 
665 Error Socket::PreDisconnect()
666 {
667     Error error;
668     return error;
669 }
670 
671 Error Socket::Close()
672 {
673     Error error;
674     if (!IsValid() || !m_should_close_fd)
675         return error;
676 
677     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
678     if (log)
679         log->Printf ("%p Socket::Close (fd = %i)", static_cast<void*>(this), m_socket);
680 
681 #if defined(_WIN32)
682     bool success = !!closesocket(m_socket);
683 #else
684     bool success = !!::close (m_socket);
685 #endif
686     // A reference to a FD was passed in, set it to an invalid value
687     m_socket = kInvalidSocketValue;
688     if (!success)
689     {
690         SetLastError (error);
691     }
692 
693     return error;
694 }
695 
696 
697 int Socket::GetOption(int level, int option_name, int &option_value)
698 {
699     get_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
700     socklen_t option_value_size = sizeof(int);
701 	return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size);
702 }
703 
704 int Socket::SetOption(int level, int option_name, int option_value)
705 {
706     set_socket_option_arg_type option_value_p = reinterpret_cast<get_socket_option_arg_type>(&option_value);
707 	return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value));
708 }
709 
710 uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket)
711 {
712     // We bound to port zero, so we need to figure out which port we actually bound to
713     if (socket != kInvalidSocketValue)
714     {
715         SocketAddress sock_addr;
716         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
717         if (::getsockname (socket, sock_addr, &sock_addr_len) == 0)
718             return sock_addr.GetPort ();
719     }
720     return 0;
721 }
722 
723 // Return the port number that is being used by the socket.
724 uint16_t Socket::GetLocalPortNumber() const
725 {
726     return GetLocalPortNumber (m_socket);
727 }
728 
729 std::string  Socket::GetLocalIPAddress () const
730 {
731     // We bound to port zero, so we need to figure out which port we actually bound to
732     if (m_socket != kInvalidSocketValue)
733     {
734         SocketAddress sock_addr;
735         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
736         if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0)
737             return sock_addr.GetIPAddress ();
738     }
739     return "";
740 }
741 
742 uint16_t Socket::GetRemotePortNumber () const
743 {
744     if (m_socket != kInvalidSocketValue)
745     {
746         SocketAddress sock_addr;
747         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
748         if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
749             return sock_addr.GetPort ();
750     }
751     return 0;
752 }
753 
754 std::string Socket::GetRemoteIPAddress () const
755 {
756     // We bound to port zero, so we need to figure out which port we actually bound to
757     if (m_socket != kInvalidSocketValue)
758     {
759         SocketAddress sock_addr;
760         socklen_t sock_addr_len = sock_addr.GetMaxLength ();
761         if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0)
762             return sock_addr.GetIPAddress ();
763     }
764     return "";
765 }
766 
767 
768