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