ConnectionFileDescriptor.cpp revision 36f63a92bae332929e1a047b59ed6df651d8537f
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 Log *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 Log *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 Log *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 if (log) 329 log->Printf("%p ConnectionFileDescriptor::Write() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...", 330 this, nfds, m_fd, tv_ptr); 331 332 const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr); 333 if (num_set_fds < 0) 334 error.SetErrorToErrno(); 335 else 336 error.Clear(); 337 338 if (log) 339 log->Printf("%p ConnectionFileDescriptor::Write() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s", 340 this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString()); 341 342 if (error_ptr) 343 *error_ptr = error; 344 345 if (error.Fail()) 346 { 347 switch (error.GetError()) 348 { 349 case EBADF: // One of the descriptor sets specified an invalid descriptor. 350 case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. 351 default: // Other unknown error 352 return eConnectionStatusError; 353 354 case EAGAIN: // The kernel was (perhaps temporarily) unable to 355 // allocate the requested number of file descriptors, 356 // or we have non-blocking IO 357 case EINTR: // A signal was delivered before the time limit 358 // expired and before any of the selected events 359 // occurred. 360 break; // Lets keep reading to until we timeout 361 } 362 } 363 else if (num_set_fds == 0) 364 { 365 return eConnectionStatusTimedOut; 366 } 367 else if (num_set_fds > 0) 368 { 369 return eConnectionStatusSuccess; 370 } 371 } 372 373 if (error_ptr) 374 error_ptr->SetErrorString("Not connected."); 375 return eConnectionStatusLostConnection; 376} 377 378ConnectionStatus 379ConnectionFileDescriptor::Close (int& fd, Error *error_ptr) 380{ 381 if (error_ptr) 382 error_ptr->Clear(); 383 bool success = true; 384 if (fd >= 0) 385 { 386 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 387 "%p ConnectionFileDescriptor::Close (fd = %i)", 388 this, 389 fd); 390 391 success = ::close (fd) == 0; 392 if (!success && error_ptr) 393 { 394 // Only set the error if we have been asked to since something else 395 // might have caused us to try and shut down the connection and may 396 // have already set the error. 397 error_ptr->SetErrorToErrno(); 398 } 399 fd = -1; 400 } 401 m_is_socket = false; 402 if (success) 403 return eConnectionStatusSuccess; 404 else 405 return eConnectionStatusError; 406} 407 408ConnectionStatus 409ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr) 410{ 411 ConnectionStatus result = eConnectionStatusError; 412 struct sockaddr_un saddr_un; 413 414 m_is_socket = true; 415 416 int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0); 417 if (listen_socket == -1) 418 { 419 if (error_ptr) 420 error_ptr->SetErrorToErrno(); 421 return eConnectionStatusError; 422 } 423 424 saddr_un.sun_family = AF_UNIX; 425 ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1); 426 saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; 427 saddr_un.sun_len = SUN_LEN (&saddr_un); 428 429 if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0) 430 { 431 if (::listen (listen_socket, 5) == 0) 432 { 433 m_fd = ::accept (listen_socket, NULL, 0); 434 if (m_fd > 0) 435 { 436 m_should_close_fd = true; 437 438 if (error_ptr) 439 error_ptr->Clear(); 440 result = eConnectionStatusSuccess; 441 } 442 } 443 } 444 445 if (result != eConnectionStatusSuccess) 446 { 447 if (error_ptr) 448 error_ptr->SetErrorToErrno(); 449 } 450 // We are done with the listen port 451 Close (listen_socket, NULL); 452 return result; 453} 454 455ConnectionStatus 456ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr) 457{ 458 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 459 "%p ConnectionFileDescriptor::SocketListen (port = %i)", 460 this, listen_port_num); 461 462 Close (m_fd, NULL); 463 m_is_socket = true; 464 int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 465 if (listen_port == -1) 466 { 467 if (error_ptr) 468 error_ptr->SetErrorToErrno(); 469 return eConnectionStatusError; 470 } 471 472 // enable local address reuse 473 SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1); 474 475 struct sockaddr_in sa; 476 ::memset (&sa, 0, sizeof sa); 477 sa.sin_family = AF_INET; 478 sa.sin_port = htons (listen_port_num); 479 sa.sin_addr.s_addr = htonl (INADDR_ANY); 480 481 int err = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa)); 482 if (err == -1) 483 { 484 if (error_ptr) 485 error_ptr->SetErrorToErrno(); 486 Close (listen_port, NULL); 487 return eConnectionStatusError; 488 } 489 490 err = ::listen (listen_port, 1); 491 if (err == -1) 492 { 493 if (error_ptr) 494 error_ptr->SetErrorToErrno(); 495 Close (listen_port, NULL); 496 return eConnectionStatusError; 497 } 498 499 m_fd = ::accept (listen_port, NULL, 0); 500 if (m_fd == -1) 501 { 502 if (error_ptr) 503 error_ptr->SetErrorToErrno(); 504 Close (listen_port, NULL); 505 return eConnectionStatusError; 506 } 507 508 // We are done with the listen port 509 Close (listen_port, NULL); 510 511 m_should_close_fd = true; 512 513 // Keep our TCP packets coming without any delays. 514 SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 515 if (error_ptr) 516 error_ptr->Clear(); 517 return eConnectionStatusSuccess; 518} 519 520ConnectionStatus 521ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr) 522{ 523 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, 524 "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)", 525 this, host_and_port); 526 Close (m_fd, NULL); 527 m_is_socket = true; 528 529 RegularExpression regex ("([^:]+):([0-9]+)"); 530 if (regex.Execute (host_and_port, 2) == false) 531 { 532 if (error_ptr) 533 error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port); 534 return eConnectionStatusError; 535 } 536 std::string host_str; 537 std::string port_str; 538 if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false || 539 regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) 540 { 541 if (error_ptr) 542 error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port); 543 return eConnectionStatusError; 544 } 545 546 int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); 547 if (port == INT32_MIN) 548 { 549 if (error_ptr) 550 error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str()); 551 return eConnectionStatusError; 552 } 553 // Create the socket 554 m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 555 if (m_fd == -1) 556 { 557 if (error_ptr) 558 error_ptr->SetErrorToErrno(); 559 return eConnectionStatusError; 560 } 561 562 m_should_close_fd = true; 563 564 // Enable local address reuse 565 SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); 566 567 struct sockaddr_in sa; 568 ::bzero (&sa, sizeof (sa)); 569 sa.sin_family = AF_INET; 570 sa.sin_port = htons (port); 571 572 int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); 573 574 if (inet_pton_result <= 0) 575 { 576 struct hostent *host_entry = gethostbyname (host_str.c_str()); 577 if (host_entry) 578 host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); 579 inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); 580 if (inet_pton_result <= 0) 581 { 582 583 if (error_ptr) 584 { 585 if (inet_pton_result == -1) 586 error_ptr->SetErrorToErrno(); 587 else 588 error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str()); 589 } 590 Close (m_fd, NULL); 591 return eConnectionStatusError; 592 } 593 } 594 595 if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) 596 { 597 if (error_ptr) 598 error_ptr->SetErrorToErrno(); 599 Close (m_fd, NULL); 600 return eConnectionStatusError; 601 } 602 603 // Keep our TCP packets coming without any delays. 604 SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 605 if (error_ptr) 606 error_ptr->Clear(); 607 return eConnectionStatusSuccess; 608} 609 610int 611ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value) 612{ 613 return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); 614} 615 616 617