ConnectionFileDescriptor.cpp revision e005f2ce03c489ebde9110678a29cbfe8488d5b4
1//===-- ConnectionFileDescriptor.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/Core/ConnectionFileDescriptor.h" 11 12// C Includes 13#include <arpa/inet.h> 14#include <errno.h> 15#include <fcntl.h> 16#include <netdb.h> 17#include <netinet/in.h> 18#include <netinet/tcp.h> 19#include <sys/socket.h> 20#include <sys/types.h> 21#include <sys/un.h> 22#include <string.h> 23#include <stdlib.h> 24 25// C++ Includes 26// Other libraries and framework includes 27// Project includes 28#include "lldb/lldb-private-log.h" 29#include "lldb/Interpreter/Args.h" 30#include "lldb/Core/Communication.h" 31#include "lldb/Core/Log.h" 32#include "lldb/Core/RegularExpression.h" 33#include "lldb/Core/Timer.h" 34 35using namespace lldb; 36using namespace lldb_private; 37 38ConnectionFileDescriptor::ConnectionFileDescriptor () : 39 Connection(), 40 m_fd (-1), 41 m_should_close_fd (false) 42{ 43 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, 44 "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", 45 this); 46} 47 48ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) : 49 Connection(), 50 m_fd (fd), 51 m_should_close_fd (owns_fd) 52{ 53 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, 54 "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", 55 this, fd, owns_fd); 56} 57 58 59ConnectionFileDescriptor::~ConnectionFileDescriptor () 60{ 61 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, 62 "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", 63 this); 64 Disconnect (NULL); 65} 66 67bool 68ConnectionFileDescriptor::IsConnected () const 69{ 70 return m_fd >= 0; 71} 72 73ConnectionStatus 74ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) 75{ 76 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 77 "%p ConnectionFileDescriptor::Connect (url = '%s')", 78 this, s); 79 80 if (s && s[0]) 81 { 82 char *end = NULL; 83 if (strstr(s, "listen://")) 84 { 85 // listen://HOST:PORT 86 unsigned long listen_port = ::strtoul(s + strlen("listen://"), &end, 0); 87 return SocketListen (listen_port, error_ptr); 88 } 89 else if (strstr(s, "unix-accept://")) 90 { 91 // unix://SOCKNAME 92 return NamedSocketAccept (s + strlen("unix-accept://"), error_ptr); 93 } 94 else if (strstr(s, "connect://")) 95 { 96 return SocketConnect (s + strlen("connect://"), error_ptr); 97 } 98 else if (strstr(s, "file://")) 99 { 100 // file:///PATH 101 const char *path = s + strlen("file://"); 102 m_fd = ::open (path, O_RDWR); 103 if (m_fd == -1) 104 { 105 if (error_ptr) 106 error_ptr->SetErrorToErrno(); 107 return eConnectionStatusError; 108 } 109 110 int flags = ::fcntl (m_fd, F_GETFL, 0); 111 if (flags >= 0) 112 { 113 if ((flags & O_NONBLOCK) == 0) 114 { 115 flags |= O_NONBLOCK; 116 ::fcntl (m_fd, F_SETFL, flags); 117 } 118 } 119 m_should_close_fd = true; 120 return eConnectionStatusSuccess; 121 } 122 if (error_ptr) 123 error_ptr->SetErrorStringWithFormat ("Unsupported connection URL: '%s'.\n", s); 124 return eConnectionStatusError; 125 } 126 if (error_ptr) 127 error_ptr->SetErrorString("NULL connection URL."); 128 return eConnectionStatusError; 129} 130 131ConnectionStatus 132ConnectionFileDescriptor::Disconnect (Error *error_ptr) 133{ 134 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 135 "%p ConnectionFileDescriptor::Disconnect ()", 136 this); 137 if (m_should_close_fd == false) 138 { 139 m_fd = -1; 140 return eConnectionStatusSuccess; 141 } 142 return Close (m_fd, error_ptr); 143} 144 145size_t 146ConnectionFileDescriptor::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr) 147{ 148 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); 149 if (log) 150 log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...", 151 this, m_fd, dst, dst_len); 152 153 Error error; 154 ssize_t bytes_read = ::read (m_fd, dst, dst_len); 155 if (bytes_read == 0) 156 { 157 error.SetErrorStringWithFormat("End-of-file.\n"); 158 status = eConnectionStatusLostConnection; 159 } 160 else if (bytes_read < 0) 161 { 162 error.SetErrorToErrno(); 163 } 164 else 165 { 166 error.Clear(); 167 } 168 169 if (log) 170 log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu) => %zi, error = %s", 171 this, 172 m_fd, 173 dst, 174 dst_len, 175 bytes_read, 176 error.AsCString()); 177 178 if (error_ptr) 179 *error_ptr = error; 180 181 if (error.Fail()) 182 { 183 uint32_t error_value = error.GetError(); 184 switch (error_value) 185 { 186 case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. 187 status = eConnectionStatusSuccess; 188 return 0; 189 190 case EBADF: // fildes is not a valid file or socket descriptor open for reading. 191 case EFAULT: // Buf points outside the allocated address space. 192 case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. 193 case EINVAL: // The pointer associated with fildes was negative. 194 case EIO: // An I/O error occurred while reading from the file system. 195 // The process group is orphaned. 196 // The file is a regular file, nbyte is greater than 0, 197 // the starting position is before the end-of-file, and 198 // the starting position is greater than or equal to the 199 // offset maximum established for the open file 200 // descriptor associated with fildes. 201 case EISDIR: // An attempt is made to read a directory. 202 case ENOBUFS: // An attempt to allocate a memory buffer fails. 203 case ENOMEM: // Insufficient memory is available. 204 status = eConnectionStatusError; 205 break; // Break to close.... 206 207 case ENXIO: // An action is requested of a device that does not exist.. 208 // A requested action cannot be performed by the device. 209 case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket. 210 case ENOTCONN: // A read is attempted on an unconnected socket. 211 status = eConnectionStatusLostConnection; 212 break; // Break to close.... 213 214 case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. 215 status = eConnectionStatusTimedOut; 216 return 0; 217 } 218 219// if (log) 220// error->Log(log, "::read ( %i, %p, %zu ) => %i", m_fd, dst, dst_len, bytesread); 221 Close (m_fd, NULL); 222 return 0; 223 } 224 return bytes_read; 225} 226 227size_t 228ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) 229{ 230 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); 231 if (log) 232 log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %zu)", this, src, src_len); 233 234 if (!IsConnected ()) 235 { 236 if (error_ptr) 237 error_ptr->SetErrorString("Not connected."); 238 status = eConnectionStatusNoConnection; 239 return 0; 240 } 241 242 243 Error error; 244 245 ssize_t bytes_sent = 0; 246 247 if (m_is_socket) 248 bytes_sent = ::send (m_fd, src, src_len, 0); 249 else 250 bytes_sent = ::write (m_fd, src, src_len); 251 252 if (bytes_sent < 0) 253 error.SetErrorToErrno (); 254 else 255 error.Clear (); 256 257 if (log) 258 { 259 if (m_is_socket) 260 log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)", 261 this, m_fd, src, src_len, bytes_sent, error.AsCString()); 262 else 263 log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)", 264 this, m_fd, src, src_len, bytes_sent, error.AsCString()); 265 } 266 267 if (error_ptr) 268 *error_ptr = error; 269 270 if (error.Fail()) 271 { 272 switch (error.GetError()) 273 { 274 case EAGAIN: 275 case EINTR: 276 status = eConnectionStatusSuccess; 277 return 0; 278 279 case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket. 280 case ENOTCONN: // A read is attempted on an unconnected socket. 281 status = eConnectionStatusLostConnection; 282 break; // Break to close.... 283 284 default: 285 status = eConnectionStatusError; 286 break; // Break to close.... 287 } 288 289 Close (m_fd, NULL); 290 return 0; 291 } 292 293 status = eConnectionStatusSuccess; 294 return bytes_sent; 295} 296 297ConnectionStatus 298ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) 299{ 300 LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); 301 if (log) 302 log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec); 303 struct timeval *tv_ptr; 304 struct timeval tv; 305 if (timeout_usec == UINT32_MAX) 306 { 307 // Infinite wait... 308 tv_ptr = NULL; 309 } 310 else 311 { 312 TimeValue time_value; 313 time_value.OffsetWithMicroSeconds (timeout_usec); 314 tv = time_value.GetAsTimeVal(); 315 tv_ptr = &tv; 316 } 317 318 while (IsConnected()) 319 { 320 fd_set read_fds; 321 FD_ZERO (&read_fds); 322 FD_SET (m_fd, &read_fds); 323 int nfds = m_fd + 1; 324 325 Error error; 326 327 328 log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION); 329 if (log) 330 log->Printf("%p ConnectionFileDescriptor::Write() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...", 331 this, nfds, m_fd, tv_ptr); 332 333 const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr); 334 if (num_set_fds < 0) 335 error.SetErrorToErrno(); 336 else 337 error.Clear(); 338 339 log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION); 340 if (log) 341 log->Printf("%p ConnectionFileDescriptor::Write() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s", 342 this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString()); 343 344 if (error_ptr) 345 *error_ptr = error; 346 347 if (error.Fail()) 348 { 349 switch (error.GetError()) 350 { 351 case EBADF: // One of the descriptor sets specified an invalid descriptor. 352 case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. 353 default: // Other unknown error 354 return eConnectionStatusError; 355 356 case EAGAIN: // The kernel was (perhaps temporarily) unable to 357 // allocate the requested number of file descriptors, 358 // or we have non-blocking IO 359 case EINTR: // A signal was delivered before the time limit 360 // expired and before any of the selected events 361 // occurred. 362 break; // Lets keep reading to until we timeout 363 } 364 } 365 else if (num_set_fds == 0) 366 { 367 return eConnectionStatusTimedOut; 368 } 369 else if (num_set_fds > 0) 370 { 371 return eConnectionStatusSuccess; 372 } 373 } 374 375 if (error_ptr) 376 error_ptr->SetErrorString("Not connected."); 377 return eConnectionStatusLostConnection; 378} 379 380ConnectionStatus 381ConnectionFileDescriptor::Close (int& fd, Error *error_ptr) 382{ 383 if (error_ptr) 384 error_ptr->Clear(); 385 bool success = true; 386 if (fd >= 0) 387 { 388 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 389 "%p ConnectionFileDescriptor::Close (fd = %i)", 390 this, 391 fd); 392 393 success = ::close (fd) == 0; 394 if (!success && error_ptr) 395 { 396 // Only set the error if we have been asked to since something else 397 // might have caused us to try and shut down the connection and may 398 // have already set the error. 399 error_ptr->SetErrorToErrno(); 400 } 401 fd = -1; 402 } 403 m_is_socket = false; 404 if (success) 405 return eConnectionStatusSuccess; 406 else 407 return eConnectionStatusError; 408} 409 410ConnectionStatus 411ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr) 412{ 413 ConnectionStatus result = eConnectionStatusError; 414 struct sockaddr_un saddr_un; 415 416 m_is_socket = true; 417 418 int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0); 419 if (listen_socket == -1) 420 { 421 if (error_ptr) 422 error_ptr->SetErrorToErrno(); 423 return eConnectionStatusError; 424 } 425 426 saddr_un.sun_family = AF_UNIX; 427 ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1); 428 saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; 429 saddr_un.sun_len = SUN_LEN (&saddr_un); 430 431 if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0) 432 { 433 if (::listen (listen_socket, 5) == 0) 434 { 435 m_fd = ::accept (listen_socket, NULL, 0); 436 if (m_fd > 0) 437 { 438 m_should_close_fd = true; 439 440 if (error_ptr) 441 error_ptr->Clear(); 442 result = eConnectionStatusSuccess; 443 } 444 } 445 } 446 447 if (result != eConnectionStatusSuccess) 448 { 449 if (error_ptr) 450 error_ptr->SetErrorToErrno(); 451 } 452 // We are done with the listen port 453 Close (listen_socket, NULL); 454 return result; 455} 456 457ConnectionStatus 458ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr) 459{ 460 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 461 "%p ConnectionFileDescriptor::SocketListen (port = %i)", 462 this, listen_port_num); 463 464 Close (m_fd, NULL); 465 m_is_socket = true; 466 int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 467 if (listen_port == -1) 468 { 469 if (error_ptr) 470 error_ptr->SetErrorToErrno(); 471 return eConnectionStatusError; 472 } 473 474 // enable local address reuse 475 SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1); 476 477 struct sockaddr_in sa; 478 ::memset (&sa, 0, sizeof sa); 479 sa.sin_family = AF_INET; 480 sa.sin_port = htons (listen_port_num); 481 sa.sin_addr.s_addr = htonl (INADDR_ANY); 482 483 int err = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa)); 484 if (err == -1) 485 { 486 if (error_ptr) 487 error_ptr->SetErrorToErrno(); 488 Close (listen_port, NULL); 489 return eConnectionStatusError; 490 } 491 492 err = ::listen (listen_port, 1); 493 if (err == -1) 494 { 495 if (error_ptr) 496 error_ptr->SetErrorToErrno(); 497 Close (listen_port, NULL); 498 return eConnectionStatusError; 499 } 500 501 m_fd = ::accept (listen_port, NULL, 0); 502 if (m_fd == -1) 503 { 504 if (error_ptr) 505 error_ptr->SetErrorToErrno(); 506 Close (listen_port, NULL); 507 return eConnectionStatusError; 508 } 509 510 // We are done with the listen port 511 Close (listen_port, NULL); 512 513 m_should_close_fd = true; 514 515 // Keep our TCP packets coming without any delays. 516 SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 517 if (error_ptr) 518 error_ptr->Clear(); 519 return eConnectionStatusSuccess; 520} 521 522ConnectionStatus 523ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr) 524{ 525 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 526 "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)", 527 this, host_and_port); 528 Close (m_fd, NULL); 529 m_is_socket = true; 530 531 RegularExpression regex ("([^:]+):([0-9]+)"); 532 if (regex.Execute (host_and_port, 2) == false) 533 { 534 if (error_ptr) 535 error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port); 536 return eConnectionStatusError; 537 } 538 std::string host_str; 539 std::string port_str; 540 if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false || 541 regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) 542 { 543 if (error_ptr) 544 error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port); 545 return eConnectionStatusError; 546 } 547 548 int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); 549 if (port == INT32_MIN) 550 { 551 if (error_ptr) 552 error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str()); 553 return eConnectionStatusError; 554 } 555 // Create the socket 556 m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 557 if (m_fd == -1) 558 { 559 if (error_ptr) 560 error_ptr->SetErrorToErrno(); 561 return eConnectionStatusError; 562 } 563 564 m_should_close_fd = true; 565 566 // Enable local address reuse 567 SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); 568 569 struct sockaddr_in sa; 570 ::bzero (&sa, sizeof (sa)); 571 sa.sin_family = AF_INET; 572 sa.sin_port = htons (port); 573 574 int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); 575 576 if (inet_pton_result <= 0) 577 { 578 struct hostent *host_entry = gethostbyname (host_str.c_str()); 579 if (host_entry) 580 host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); 581 inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); 582 if (inet_pton_result <= 0) 583 { 584 585 if (error_ptr) 586 { 587 if (inet_pton_result == -1) 588 error_ptr->SetErrorToErrno(); 589 else 590 error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str()); 591 } 592 Close (m_fd, NULL); 593 return eConnectionStatusError; 594 } 595 } 596 597 if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) 598 { 599 if (error_ptr) 600 error_ptr->SetErrorToErrno(); 601 Close (m_fd, NULL); 602 return eConnectionStatusError; 603 } 604 605 // Keep our TCP packets coming without any delays. 606 SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 607 if (error_ptr) 608 error_ptr->Clear(); 609 return eConnectionStatusSuccess; 610} 611 612int 613ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value) 614{ 615 return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); 616} 617 618 619