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