1 //===-- ConnectionFileDescriptorPosix.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 #if defined(__APPLE__) 11 // Enable this special support for Apple builds where we can have unlimited 12 // select bounds. We tried switching to poll() and kqueue and we were panicing 13 // the kernel, so we have to stick with select for now. 14 #define _DARWIN_UNLIMITED_SELECT 15 #endif 16 17 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" 18 #include "lldb/Host/Config.h" 19 #include "lldb/Host/IOObject.h" 20 #include "lldb/Host/SocketAddress.h" 21 #include "lldb/Host/Socket.h" 22 #include "lldb/Host/StringConvert.h" 23 24 // C Includes 25 #include <errno.h> 26 #include <fcntl.h> 27 #include <string.h> 28 #include <stdlib.h> 29 #include <sys/types.h> 30 31 #ifndef LLDB_DISABLE_POSIX 32 #include <termios.h> 33 #endif 34 35 // C++ Includes 36 // Other libraries and framework includes 37 #include "llvm/Support/ErrorHandling.h" 38 #if defined(__APPLE__) 39 #include "llvm/ADT/SmallVector.h" 40 #endif 41 // Project includes 42 #include "lldb/Core/Communication.h" 43 #include "lldb/Core/Log.h" 44 #include "lldb/Core/StreamString.h" 45 #include "lldb/Core/Timer.h" 46 #include "lldb/Host/Host.h" 47 #include "lldb/Host/Socket.h" 48 #include "lldb/Interpreter/Args.h" 49 50 using namespace lldb; 51 using namespace lldb_private; 52 53 ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) 54 : Connection() 55 , m_pipe() 56 , m_mutex(Mutex::eMutexTypeRecursive) 57 , m_shutting_down(false) 58 , m_waiting_for_accept(false) 59 , m_child_processes_inherit(child_processes_inherit) 60 { 61 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); 62 if (log) 63 log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast<void *>(this)); 64 } 65 66 ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) 67 : Connection() 68 , m_pipe() 69 , m_mutex(Mutex::eMutexTypeRecursive) 70 , m_shutting_down(false) 71 , m_waiting_for_accept(false) 72 , m_child_processes_inherit(false) 73 { 74 m_write_sp.reset(new File(fd, owns_fd)); 75 m_read_sp.reset(new File(fd, false)); 76 77 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); 78 if (log) 79 log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", static_cast<void *>(this), fd, 80 owns_fd); 81 OpenCommandPipe(); 82 } 83 84 ConnectionFileDescriptor::ConnectionFileDescriptor(Socket* socket) 85 : Connection() 86 , m_pipe() 87 , m_mutex(Mutex::eMutexTypeRecursive) 88 , m_shutting_down(false) 89 , m_waiting_for_accept(false) 90 , m_child_processes_inherit(false) 91 { 92 InitializeSocket(socket); 93 } 94 95 ConnectionFileDescriptor::~ConnectionFileDescriptor() 96 { 97 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); 98 if (log) 99 log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast<void *>(this)); 100 Disconnect(NULL); 101 CloseCommandPipe(); 102 } 103 104 void 105 ConnectionFileDescriptor::OpenCommandPipe() 106 { 107 CloseCommandPipe(); 108 109 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 110 // Make the command file descriptor here: 111 Error result = m_pipe.CreateNew(m_child_processes_inherit); 112 if (!result.Success()) 113 { 114 if (log) 115 log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this), 116 result.AsCString()); 117 } 118 else 119 { 120 if (log) 121 log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this), 122 m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); 123 } 124 } 125 126 void 127 ConnectionFileDescriptor::CloseCommandPipe() 128 { 129 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 130 if (log) 131 log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast<void *>(this)); 132 133 m_pipe.Close(); 134 } 135 136 bool 137 ConnectionFileDescriptor::IsConnected() const 138 { 139 return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); 140 } 141 142 ConnectionStatus 143 ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) 144 { 145 Mutex::Locker locker(m_mutex); 146 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 147 if (log) 148 log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast<void *>(this), s); 149 150 OpenCommandPipe(); 151 152 if (s && s[0]) 153 { 154 if (strstr(s, "listen://") == s) 155 { 156 // listen://HOST:PORT 157 return SocketListenAndAccept(s + strlen("listen://"), error_ptr); 158 } 159 else if (strstr(s, "accept://") == s) 160 { 161 // unix://SOCKNAME 162 return NamedSocketAccept(s + strlen("accept://"), error_ptr); 163 } 164 else if (strstr(s, "unix-accept://") == s) 165 { 166 // unix://SOCKNAME 167 return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr); 168 } 169 else if (strstr(s, "connect://") == s) 170 { 171 return ConnectTCP(s + strlen("connect://"), error_ptr); 172 } 173 else if (strstr(s, "tcp-connect://") == s) 174 { 175 return ConnectTCP(s + strlen("tcp-connect://"), error_ptr); 176 } 177 else if (strstr(s, "udp://") == s) 178 { 179 return ConnectUDP(s + strlen("udp://"), error_ptr); 180 } 181 #ifndef LLDB_DISABLE_POSIX 182 else if (strstr(s, "fd://") == s) 183 { 184 // Just passing a native file descriptor within this current process 185 // that is already opened (possibly from a service or other source). 186 s += strlen("fd://"); 187 bool success = false; 188 int fd = StringConvert::ToSInt32(s, -1, 0, &success); 189 190 if (success) 191 { 192 // We have what looks to be a valid file descriptor, but we 193 // should make sure it is. We currently are doing this by trying to 194 // get the flags from the file descriptor and making sure it 195 // isn't a bad fd. 196 errno = 0; 197 int flags = ::fcntl(fd, F_GETFL, 0); 198 if (flags == -1 || errno == EBADF) 199 { 200 if (error_ptr) 201 error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); 202 m_read_sp.reset(); 203 m_write_sp.reset(); 204 return eConnectionStatusError; 205 } 206 else 207 { 208 // Don't take ownership of a file descriptor that gets passed 209 // to us since someone else opened the file descriptor and 210 // handed it to us. 211 // TODO: Since are using a URL to open connection we should 212 // eventually parse options using the web standard where we 213 // have "fd://123?opt1=value;opt2=value" and we can have an 214 // option be "owns=1" or "owns=0" or something like this to 215 // allow us to specify this. For now, we assume we must 216 // assume we don't own it. 217 218 std::unique_ptr<Socket> tcp_socket; 219 tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false)); 220 // Try and get a socket option from this file descriptor to 221 // see if this is a socket and set m_is_socket accordingly. 222 int resuse; 223 bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); 224 if (is_socket) 225 { 226 m_read_sp = std::move(tcp_socket); 227 m_write_sp = m_read_sp; 228 } 229 else 230 { 231 m_read_sp.reset(new File(fd, false)); 232 m_write_sp.reset(new File(fd, false)); 233 } 234 m_uri.assign(s); 235 return eConnectionStatusSuccess; 236 } 237 } 238 239 if (error_ptr) 240 error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"fd://%s\"", s); 241 m_read_sp.reset(); 242 m_write_sp.reset(); 243 return eConnectionStatusError; 244 } 245 else if (strstr(s, "file://") == s) 246 { 247 // file:///PATH 248 const char *path = s + strlen("file://"); 249 int fd = -1; 250 do 251 { 252 fd = ::open(path, O_RDWR); 253 } while (fd == -1 && errno == EINTR); 254 255 if (fd == -1) 256 { 257 if (error_ptr) 258 error_ptr->SetErrorToErrno(); 259 return eConnectionStatusError; 260 } 261 262 if (::isatty(fd)) 263 { 264 // Set up serial terminal emulation 265 struct termios options; 266 ::tcgetattr(fd, &options); 267 268 // Set port speed to maximum 269 ::cfsetospeed(&options, B115200); 270 ::cfsetispeed(&options, B115200); 271 272 // Raw input, disable echo and signals 273 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 274 275 // Make sure only one character is needed to return from a read 276 options.c_cc[VMIN] = 1; 277 options.c_cc[VTIME] = 0; 278 279 ::tcsetattr(fd, TCSANOW, &options); 280 } 281 282 int flags = ::fcntl(fd, F_GETFL, 0); 283 if (flags >= 0) 284 { 285 if ((flags & O_NONBLOCK) == 0) 286 { 287 flags |= O_NONBLOCK; 288 ::fcntl(fd, F_SETFL, flags); 289 } 290 } 291 m_read_sp.reset(new File(fd, true)); 292 m_write_sp.reset(new File(fd, false)); 293 return eConnectionStatusSuccess; 294 } 295 #endif 296 if (error_ptr) 297 error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); 298 return eConnectionStatusError; 299 } 300 if (error_ptr) 301 error_ptr->SetErrorString("invalid connect arguments"); 302 return eConnectionStatusError; 303 } 304 305 bool 306 ConnectionFileDescriptor::InterruptRead() 307 { 308 size_t bytes_written = 0; 309 Error result = m_pipe.Write("i", 1, bytes_written); 310 return result.Success(); 311 } 312 313 ConnectionStatus 314 ConnectionFileDescriptor::Disconnect(Error *error_ptr) 315 { 316 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 317 if (log) 318 log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast<void *>(this)); 319 320 ConnectionStatus status = eConnectionStatusSuccess; 321 322 if (!IsConnected()) 323 { 324 if (log) 325 log->Printf("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast<void *>(this)); 326 return eConnectionStatusSuccess; 327 } 328 329 if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) 330 static_cast<Socket &>(*m_read_sp).PreDisconnect(); 331 332 // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely 333 // because somebody is doing a blocking read on our file descriptor. If that's the case, 334 // then send the "q" char to the command file channel so the read will wake up and the connection 335 // will then know to shut down. 336 337 m_shutting_down = true; 338 339 Mutex::Locker locker; 340 bool got_lock = locker.TryLock(m_mutex); 341 342 if (!got_lock) 343 { 344 if (m_pipe.CanWrite()) 345 { 346 size_t bytes_written = 0; 347 Error result = m_pipe.Write("q", 1, bytes_written); 348 if (log) 349 log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, error = '%s'.", 350 static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), result.AsCString()); 351 } 352 else if (log) 353 { 354 log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", 355 static_cast<void *>(this)); 356 } 357 locker.Lock(m_mutex); 358 } 359 360 Error error = m_read_sp->Close(); 361 Error error2 = m_write_sp->Close(); 362 if (error.Fail() || error2.Fail()) 363 status = eConnectionStatusError; 364 if (error_ptr) 365 *error_ptr = error.Fail() ? error : error2; 366 367 m_uri.clear(); 368 m_shutting_down = false; 369 return status; 370 } 371 372 size_t 373 ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) 374 { 375 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 376 377 Mutex::Locker locker; 378 bool got_lock = locker.TryLock(m_mutex); 379 if (!got_lock) 380 { 381 if (log) 382 log->Printf("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", static_cast<void *>(this)); 383 if (error_ptr) 384 error_ptr->SetErrorString("failed to get the connection lock for read."); 385 386 status = eConnectionStatusTimedOut; 387 return 0; 388 } 389 390 if (m_shutting_down) 391 { 392 status = eConnectionStatusError; 393 return 0; 394 } 395 396 status = BytesAvailable(timeout_usec, error_ptr); 397 if (status != eConnectionStatusSuccess) 398 return 0; 399 400 Error error; 401 size_t bytes_read = dst_len; 402 error = m_read_sp->Read(dst, bytes_read); 403 404 if (log) 405 { 406 log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", 407 static_cast<void *>(this), static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), static_cast<void *>(dst), 408 static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read), error.AsCString()); 409 } 410 411 if (bytes_read == 0) 412 { 413 error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. 414 status = eConnectionStatusEndOfFile; 415 } 416 417 if (error_ptr) 418 *error_ptr = error; 419 420 if (error.Fail()) 421 { 422 uint32_t error_value = error.GetError(); 423 switch (error_value) 424 { 425 case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. 426 if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) 427 status = eConnectionStatusTimedOut; 428 else 429 status = eConnectionStatusSuccess; 430 return 0; 431 432 case EFAULT: // Buf points outside the allocated address space. 433 case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. 434 case EINVAL: // The pointer associated with fildes was negative. 435 case EIO: // An I/O error occurred while reading from the file system. 436 // The process group is orphaned. 437 // The file is a regular file, nbyte is greater than 0, 438 // the starting position is before the end-of-file, and 439 // the starting position is greater than or equal to the 440 // offset maximum established for the open file 441 // descriptor associated with fildes. 442 case EISDIR: // An attempt is made to read a directory. 443 case ENOBUFS: // An attempt to allocate a memory buffer fails. 444 case ENOMEM: // Insufficient memory is available. 445 status = eConnectionStatusError; 446 break; // Break to close.... 447 448 case ENOENT: // no such file or directory 449 case EBADF: // fildes is not a valid file or socket descriptor open for reading. 450 case ENXIO: // An action is requested of a device that does not exist.. 451 // A requested action cannot be performed by the device. 452 case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. 453 case ENOTCONN: // A read is attempted on an unconnected socket. 454 status = eConnectionStatusLostConnection; 455 break; // Break to close.... 456 457 case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. 458 status = eConnectionStatusTimedOut; 459 return 0; 460 461 default: 462 if (log) 463 log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", static_cast<void *>(this), 464 strerror(error_value)); 465 status = eConnectionStatusError; 466 break; // Break to close.... 467 } 468 469 return 0; 470 } 471 return bytes_read; 472 } 473 474 size_t 475 ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) 476 { 477 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 478 if (log) 479 log->Printf("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast<void *>(this), 480 static_cast<const void *>(src), static_cast<uint64_t>(src_len)); 481 482 if (!IsConnected()) 483 { 484 if (error_ptr) 485 error_ptr->SetErrorString("not connected"); 486 status = eConnectionStatusNoConnection; 487 return 0; 488 } 489 490 Error error; 491 492 size_t bytes_sent = src_len; 493 error = m_write_sp->Write(src, bytes_sent); 494 495 if (log) 496 { 497 log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", 498 static_cast<void *>(this), static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), static_cast<const void *>(src), 499 static_cast<uint64_t>(src_len), static_cast<uint64_t>(bytes_sent), error.AsCString()); 500 } 501 502 if (error_ptr) 503 *error_ptr = error; 504 505 if (error.Fail()) 506 { 507 switch (error.GetError()) 508 { 509 case EAGAIN: 510 case EINTR: 511 status = eConnectionStatusSuccess; 512 return 0; 513 514 case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. 515 case ENOTCONN: // A read is attempted on an unconnected socket. 516 status = eConnectionStatusLostConnection; 517 break; // Break to close.... 518 519 default: 520 status = eConnectionStatusError; 521 break; // Break to close.... 522 } 523 524 return 0; 525 } 526 527 status = eConnectionStatusSuccess; 528 return bytes_sent; 529 } 530 531 std::string 532 ConnectionFileDescriptor::GetURI() 533 { 534 return m_uri; 535 } 536 537 // This ConnectionFileDescriptor::BytesAvailable() uses select(). 538 // 539 // PROS: 540 // - select is consistent across most unix platforms 541 // - The Apple specific version allows for unlimited fds in the fd_sets by 542 // setting the _DARWIN_UNLIMITED_SELECT define prior to including the 543 // required header files. 544 // CONS: 545 // - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE. 546 // This implementation will assert if it runs into that hard limit to let 547 // users know that another ConnectionFileDescriptor::BytesAvailable() should 548 // be used or a new version of ConnectionFileDescriptor::BytesAvailable() 549 // should be written for the system that is running into the limitations. 550 551 #if defined(__APPLE__) 552 #define FD_SET_DATA(fds) fds.data() 553 #else 554 #define FD_SET_DATA(fds) &fds 555 #endif 556 557 ConnectionStatus 558 ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr) 559 { 560 // Don't need to take the mutex here separately since we are only called from Read. If we 561 // ever get used more generally we will need to lock here as well. 562 563 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); 564 if (log) 565 log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast<void *>(this), timeout_usec); 566 567 struct timeval *tv_ptr; 568 struct timeval tv; 569 if (timeout_usec == UINT32_MAX) 570 { 571 // Inifinite wait... 572 tv_ptr = nullptr; 573 } 574 else 575 { 576 TimeValue time_value; 577 time_value.OffsetWithMicroSeconds(timeout_usec); 578 tv.tv_sec = time_value.seconds(); 579 tv.tv_usec = time_value.microseconds(); 580 tv_ptr = &tv; 581 } 582 583 // Make a copy of the file descriptors to make sure we don't 584 // have another thread change these values out from under us 585 // and cause problems in the loop below where like in FS_SET() 586 const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); 587 const int pipe_fd = m_pipe.GetReadFileDescriptor(); 588 589 if (handle != IOObject::kInvalidHandleValue) 590 { 591 #if defined(_MSC_VER) 592 // select() won't accept pipes on Windows. The entire Windows codepath needs to be 593 // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least 594 // this will allow ::select() to not return an error. 595 const bool have_pipe_fd = false; 596 #else 597 const bool have_pipe_fd = pipe_fd >= 0; 598 #if !defined(__APPLE__) 599 assert(handle < FD_SETSIZE); 600 if (have_pipe_fd) 601 assert(pipe_fd < FD_SETSIZE); 602 #endif 603 #endif 604 while (handle == m_read_sp->GetWaitableHandle()) 605 { 606 const int nfds = std::max<int>(handle, pipe_fd) + 1; 607 #if defined(__APPLE__) 608 llvm::SmallVector<fd_set, 1> read_fds; 609 read_fds.resize((nfds / FD_SETSIZE) + 1); 610 for (size_t i = 0; i < read_fds.size(); ++i) 611 FD_ZERO(&read_fds[i]); 612 // FD_SET doesn't bounds check, it just happily walks off the end 613 // but we have taken care of making the extra storage with our 614 // SmallVector of fd_set objects 615 #else 616 fd_set read_fds; 617 FD_ZERO(&read_fds); 618 #endif 619 FD_SET(handle, FD_SET_DATA(read_fds)); 620 if (have_pipe_fd) 621 FD_SET(pipe_fd, FD_SET_DATA(read_fds)); 622 623 Error error; 624 625 if (log) 626 { 627 if (have_pipe_fd) 628 log->Printf( 629 "%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...", 630 static_cast<void *>(this), nfds, handle, pipe_fd, static_cast<void *>(tv_ptr)); 631 else 632 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...", 633 static_cast<void *>(this), nfds, handle, static_cast<void *>(tv_ptr)); 634 } 635 636 const int num_set_fds = ::select(nfds, FD_SET_DATA(read_fds), NULL, NULL, tv_ptr); 637 if (num_set_fds < 0) 638 error.SetErrorToErrno(); 639 else 640 error.Clear(); 641 642 if (log) 643 { 644 if (have_pipe_fd) 645 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) " 646 "=> %d, error = %s", 647 static_cast<void *>(this), nfds, handle, pipe_fd, static_cast<void *>(tv_ptr), num_set_fds, 648 error.AsCString()); 649 else 650 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => " 651 "%d, error = %s", 652 static_cast<void *>(this), nfds, handle, static_cast<void *>(tv_ptr), num_set_fds, error.AsCString()); 653 } 654 655 if (error_ptr) 656 *error_ptr = error; 657 658 if (error.Fail()) 659 { 660 switch (error.GetError()) 661 { 662 case EBADF: // One of the descriptor sets specified an invalid descriptor. 663 return eConnectionStatusLostConnection; 664 665 case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. 666 default: // Other unknown error 667 return eConnectionStatusError; 668 669 case EAGAIN: // The kernel was (perhaps temporarily) unable to 670 // allocate the requested number of file descriptors, 671 // or we have non-blocking IO 672 case EINTR: // A signal was delivered before the time limit 673 // expired and before any of the selected events 674 // occurred. 675 break; // Lets keep reading to until we timeout 676 } 677 } 678 else if (num_set_fds == 0) 679 { 680 return eConnectionStatusTimedOut; 681 } 682 else if (num_set_fds > 0) 683 { 684 if (FD_ISSET(handle, FD_SET_DATA(read_fds))) 685 return eConnectionStatusSuccess; 686 if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds))) 687 { 688 // We got a command to exit. Read the data from that pipe: 689 char buffer[16]; 690 ssize_t bytes_read; 691 692 do 693 { 694 bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); 695 } while (bytes_read < 0 && errno == EINTR); 696 697 switch (buffer[0]) 698 { 699 case 'q': 700 if (log) 701 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.", 702 static_cast<void *>(this), static_cast<int>(bytes_read), buffer); 703 return eConnectionStatusEndOfFile; 704 case 'i': 705 // Interrupt the current read 706 return eConnectionStatusInterrupted; 707 } 708 } 709 } 710 } 711 } 712 713 if (error_ptr) 714 error_ptr->SetErrorString("not connected"); 715 return eConnectionStatusLostConnection; 716 } 717 718 ConnectionStatus 719 ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr) 720 { 721 Socket *socket = nullptr; 722 Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); 723 if (error_ptr) 724 *error_ptr = error; 725 m_write_sp.reset(socket); 726 m_read_sp = m_write_sp; 727 if (error.Fail()) 728 { 729 return eConnectionStatusError; 730 } 731 m_uri.assign(socket_name); 732 return eConnectionStatusSuccess; 733 } 734 735 ConnectionStatus 736 ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr) 737 { 738 Socket *socket = nullptr; 739 Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); 740 if (error_ptr) 741 *error_ptr = error; 742 m_write_sp.reset(socket); 743 m_read_sp = m_write_sp; 744 if (error.Fail()) 745 { 746 return eConnectionStatusError; 747 } 748 m_uri.assign(socket_name); 749 return eConnectionStatusSuccess; 750 } 751 752 ConnectionStatus 753 ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) 754 { 755 m_port_predicate.SetValue(0, eBroadcastNever); 756 757 Socket *socket = nullptr; 758 m_waiting_for_accept = true; 759 Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); 760 if (error_ptr) 761 *error_ptr = error; 762 if (error.Fail()) 763 return eConnectionStatusError; 764 765 std::unique_ptr<Socket> listening_socket_up; 766 767 listening_socket_up.reset(socket); 768 socket = nullptr; 769 error = listening_socket_up->BlockingAccept(s, m_child_processes_inherit, socket); 770 listening_socket_up.reset(); 771 if (error_ptr) 772 *error_ptr = error; 773 if (error.Fail()) 774 return eConnectionStatusError; 775 776 InitializeSocket(socket); 777 return eConnectionStatusSuccess; 778 } 779 780 ConnectionStatus 781 ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) 782 { 783 Socket *socket = nullptr; 784 Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); 785 if (error_ptr) 786 *error_ptr = error; 787 m_write_sp.reset(socket); 788 m_read_sp = m_write_sp; 789 if (error.Fail()) 790 { 791 return eConnectionStatusError; 792 } 793 m_uri.assign(s); 794 return eConnectionStatusSuccess; 795 } 796 797 ConnectionStatus 798 ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) 799 { 800 Socket *send_socket = nullptr; 801 Socket *recv_socket = nullptr; 802 Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket); 803 if (error_ptr) 804 *error_ptr = error; 805 m_write_sp.reset(send_socket); 806 m_read_sp.reset(recv_socket); 807 if (error.Fail()) 808 { 809 return eConnectionStatusError; 810 } 811 m_uri.assign(s); 812 return eConnectionStatusSuccess; 813 } 814 815 uint16_t 816 ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) 817 { 818 uint16_t bound_port = 0; 819 if (timeout_sec == UINT32_MAX) 820 m_port_predicate.WaitForValueNotEqualTo(0, bound_port); 821 else 822 { 823 TimeValue timeout = TimeValue::Now(); 824 timeout.OffsetWithSeconds(timeout_sec); 825 m_port_predicate.WaitForValueNotEqualTo(0, bound_port, &timeout); 826 } 827 return bound_port; 828 } 829 830 bool 831 ConnectionFileDescriptor::GetChildProcessesInherit() const 832 { 833 return m_child_processes_inherit; 834 } 835 836 void 837 ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) 838 { 839 m_child_processes_inherit = child_processes_inherit; 840 } 841 842 void 843 ConnectionFileDescriptor::InitializeSocket(Socket* socket) 844 { 845 m_write_sp.reset(socket); 846 m_read_sp = m_write_sp; 847 StreamString strm; 848 strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber()); 849 m_uri.swap(strm.GetString()); 850 } 851