13#define _DARWIN_UNLIMITED_SELECT
17#include "lldb/Host/Config.h"
39#include "llvm/Support/Errno.h"
40#include "llvm/Support/ErrorHandling.h"
42#include "llvm/ADT/SmallVector.h"
58 LLDB_LOGF(log,
"%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
59 static_cast<void *
>(
this));
69 "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = "
71 static_cast<void *
>(
this), fd, owns_fd);
76 std::unique_ptr<Socket> socket_up)
78 m_uri = socket_up->GetRemoteConnectionURI();
84 LLDB_LOGF(log,
"%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
85 static_cast<void *
>(
this));
98 "%p ConnectionFileDescriptor::OpenCommandPipe () - could not "
100 static_cast<void *
>(
this), result.
AsCString());
103 "%p ConnectionFileDescriptor::OpenCommandPipe() - success "
104 "readfd=%d writefd=%d",
105 static_cast<void *
>(
this),
m_pipe.GetReadFileDescriptor(),
106 m_pipe.GetWriteFileDescriptor());
112 LLDB_LOGF(log,
"%p ConnectionFileDescriptor::CloseCommandPipe()",
113 static_cast<void *
>(
this));
124 return Connect(path, [](llvm::StringRef) {}, error_ptr);
131 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
133 LLDB_LOGF(log,
"%p ConnectionFileDescriptor::Connect (url = '%s')",
134 static_cast<void *
>(
this), path.str().c_str());
144 llvm::StringRef scheme;
145 std::tie(scheme, path) = path.split(
"://");
152 .Cases(
"accept",
"unix-accept",
154 .Case(
"unix-abstract-accept",
156 .Cases(
"connect",
"tcp-connect",
160 .Case(
"unix-abstract-connect",
172 return (this->*method)(path, socket_id_callback, error_ptr);
178 "unsupported connection URL: '%s'", path.str().c_str());
183 return !errorToBool(
m_pipe.Write(
"i", 1).takeError());
188 LLDB_LOGF(log,
"%p ConnectionFileDescriptor::Disconnect ()",
189 static_cast<void *
>(
this));
195 log,
"%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect",
196 static_cast<void *
>(
this));
205 std::unique_lock<std::recursive_mutex> locker(
m_mutex, std::defer_lock);
206 if (!locker.try_lock()) {
208 llvm::Error err =
m_pipe.Write(
"q", 1).takeError();
210 "{0}: Couldn't get the lock, sent 'q' to {1}, error = '{2}'.",
211 this,
m_pipe.GetWriteFileDescriptor(), err);
212 consumeError(std::move(err));
215 "%p ConnectionFileDescriptor::Disconnect(): Couldn't get the "
216 "lock, but no command pipe is available.",
217 static_cast<void *
>(
this));
229 *error_ptr = std::move(
error);
245 std::unique_lock<std::recursive_mutex> locker(
m_mutex, std::defer_lock);
246 if (!locker.try_lock()) {
248 "%p ConnectionFileDescriptor::Read () failed to get the "
250 static_cast<void *
>(
this));
253 "failed to get the connection lock for read.");
271 size_t bytes_read = dst_len;
276 "{0} ConnectionFileDescriptor::Read() fd = {1}"
277 ", dst = {2}, dst_len = {3}) => {4}, error = {5}",
278 this,
m_io_sp->GetWaitableHandle(), dst, dst_len, bytes_read,
282 if (bytes_read == 0) {
289 *error_ptr =
error.Clone();
292 uint32_t error_value =
error.GetError();
293 switch (error_value) {
336 LLDB_LOG(log,
"this = {0}, unexpected error: {1}",
this,
337 llvm::sys::StrError(error_value));
352 "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64
354 static_cast<void *
>(
this),
static_cast<const void *
>(src),
355 static_cast<uint64_t
>(src_len));
373 size_t bytes_sent = src_len;
378 "{0} ConnectionFileDescriptor::Write(fd = {1}"
379 ", src = {2}, src_len = {3}) => {4} (error = {5})",
380 this,
m_io_sp->GetWaitableHandle(), src, src_len, bytes_sent,
385 *error_ptr =
error.Clone();
388 switch (
error.GetError()) {
437 LLDB_LOG(log,
"this = {0}, timeout = {1}",
this, timeout);
443 const int pipe_fd =
m_pipe.GetReadFileDescriptor();
457 const bool have_pipe_fd =
false;
459 const bool have_pipe_fd = pipe_fd >= 0;
464 while (handle ==
m_io_sp->GetWaitableHandle()) {
469 *error_ptr =
error.Clone();
472 switch (
error.GetError()) {
502 llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1);
503 assert(bytes_read == 1);
508 "%p ConnectionFileDescriptor::BytesAvailable() "
509 "got data: %c from the command channel.",
510 static_cast<void *
>(
this), c);
528 llvm::function_ref<
void(
Socket &)> post_listen_callback,
531 std::unique_ptr<Socket> listening_socket =
536 error = listening_socket->Listen(socket_name, 5);
539 post_listen_callback(*listening_socket);
540 error = listening_socket->Accept(std::nullopt, accepted_socket);
544 m_io_sp.reset(accepted_socket);
545 m_uri.assign(socket_name.str());
550 *error_ptr =
error.Clone();
556 llvm::StringRef socket_name,
562 error = socket->Connect(socket_name);
566 m_uri.assign(socket_name.str());
571 *error_ptr =
error.Clone();
580 [socket_id_callback, socket_name](
Socket &listening_socket) {
581 socket_id_callback(socket_name);
597 [socket_id_callback, socket_name](
Socket &listening_socket) {
598 socket_id_callback(socket_name);
615 [socket_id_callback](
Socket &listening_socket) {
617 static_cast<TCPSocket &
>(listening_socket).GetLocalPortNumber();
618 socket_id_callback(std::to_string(port));
646 "tcp connect failed: {0}");
650 m_uri.assign(std::string(s));
663 if (!s.getAsInteger(0, fd)) {
668 int flags = ::fcntl(fd, F_GETFL, 0);
669 if (flags == -1 || errno == EBADF) {
672 "stale file descriptor: %s", s.str().c_str());
684 std::unique_ptr<TCPSocket> tcp_socket;
685 tcp_socket = std::make_unique<TCPSocket>(fd,
false);
690 !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse);
692 m_io_sp = std::move(tcp_socket);
703 "invalid file descriptor: \"%s\"", s.str().c_str());
707 llvm_unreachable(
"this function should be only called w/ LLDB_ENABLE_POSIX");
714 std::string addr_str = s.str();
725 struct termios options;
726 ::tcgetattr(fd, &options);
730 ::cfsetospeed(&options, B115200);
731 ::cfsetispeed(&options, B115200);
733 ::cfsetospeed(&options, B57600);
734 ::cfsetispeed(&options, B57600);
736 ::cfsetospeed(&options, B38400);
737 ::cfsetispeed(&options, B38400);
739#error "Maximum Baud rate is Unknown"
743 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
746 options.c_cc[VMIN] = 1;
747 options.c_cc[VTIME] = 0;
749 llvm::sys::RetryAfterSignal(-1, ::tcsetattr, fd, TCSANOW, &options);
755 llvm_unreachable(
"this function should be only called w/ LLDB_ENABLE_POSIX");
762 llvm::StringRef path, qs;
764 std::tie(path, qs) = s.split(
'?');
766 llvm::Expected<SerialPort::Options> serial_options =
768 if (!serial_options) {
772 llvm::consumeError(serial_options.takeError());
789 llvm::consumeError(serial_sp.takeError());
792 m_io_sp = std::move(serial_sp.get());
796 llvm_unreachable(
"this function should be only called w/ LLDB_ENABLE_POSIX");
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
#define LLDB_LOG_ERROR(log, error,...)
lldb_private::Status Select()
void FDSetRead(lldb::socket_t fd)
void SetTimeout(const std::chrono::microseconds &timeout)
bool FDIsSetRead(lldb::socket_t fd) const
lldb::ConnectionStatus AcceptTCP(llvm::StringRef host_and_port, socket_id_callback_type socket_id_callback, Status *error_ptr)
ConnectionFileDescriptor()
lldb::ConnectionStatus ConnectNamedSocket(llvm::StringRef socket_name, socket_id_callback_type socket_id_callback, Status *error_ptr)
~ConnectionFileDescriptor() override
lldb::ConnectionStatus AcceptAbstractSocket(llvm::StringRef socket_name, socket_id_callback_type socket_id_callback, Status *error_ptr)
lldb::ConnectionStatus ConnectUDP(llvm::StringRef args, socket_id_callback_type socket_id_callback, Status *error_ptr)
lldb::ConnectionStatus ConnectSerialPort(llvm::StringRef args, socket_id_callback_type socket_id_callback, Status *error_ptr)
std::atomic< bool > m_shutting_down
bool InterruptRead() override
Interrupts an ongoing Read() operation.
lldb::ConnectionStatus Connect(llvm::StringRef url, Status *error_ptr) override
Connect using the connect string url.
bool IsConnected() const override
Check if the connection is valid.
lldb::ConnectionStatus AcceptNamedSocket(llvm::StringRef socket_name, socket_id_callback_type socket_id_callback, Status *error_ptr)
size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Status *error_ptr) override
The actual write function that attempts to write to the communications protocol.
std::recursive_mutex m_mutex
lldb::ConnectionStatus AcceptSocket(Socket::SocketProtocol socket_protocol, llvm::StringRef socket_name, llvm::function_ref< void(Socket &)> post_listen_callback, Status *error_ptr)
lldb::ConnectionStatus ConnectFD(llvm::StringRef args, socket_id_callback_type socket_id_callback, Status *error_ptr)
lldb::ConnectionStatus ConnectAbstractSocket(llvm::StringRef socket_name, socket_id_callback_type socket_id_callback, Status *error_ptr)
lldb::ConnectionStatus Disconnect(Status *error_ptr) override
Disconnect the communications connection if one is currently connected.
lldb::ConnectionStatus BytesAvailable(const Timeout< std::micro > &timeout, Status *error_ptr)
lldb::ConnectionStatus ConnectFile(llvm::StringRef args, socket_id_callback_type socket_id_callback, Status *error_ptr)
lldb::ConnectionStatus ConnectSocket(Socket::SocketProtocol socket_protocol, llvm::StringRef socket_name, Status *error_ptr)
std::string GetURI() override
Returns a URI that describes this connection object.
lldb::ConnectionStatus ConnectTCP(llvm::StringRef host_and_port, socket_id_callback_type socket_id_callback, Status *error_ptr)
size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr) override
The read function that attempts to read from the connection.
llvm::function_ref< void(llvm::StringRef local_socket_id)> socket_id_callback_type
Connection()=default
Default constructor.
int Open(const char *path, int flags, int mode=0600)
Wraps open in a platform-independent way.
static FileSystem & Instance()
static const WaitableHandle kInvalidHandleValue
lldb::file_t WaitableHandle
static llvm::Expected< std::unique_ptr< SerialPort > > Create(int fd, OpenOptions options, Options serial_options, bool transfer_ownership)
static llvm::Expected< Options > OptionsFromURL(llvm::StringRef urlqs)
static std::unique_ptr< Socket > Create(const SocketProtocol protocol, Status &error)
static llvm::Expected< std::unique_ptr< UDPSocket > > UdpConnect(llvm::StringRef host_and_port)
static Status FromErrno()
Set the current error to errno.
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
bool Success() const
Test for success condition.
std::string GetRemoteConnectionURI() const override
#define UNUSED_IF_ASSERT_DISABLED(x)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
ConnectionStatus
Connection Status Types.
@ eConnectionStatusError
Check GetError() for details.
@ eConnectionStatusInterrupted
Interrupted read.
@ eConnectionStatusTimedOut
Request timed out.
@ eConnectionStatusEndOfFile
End-of-file encountered.
@ eConnectionStatusSuccess
Success.
@ eConnectionStatusLostConnection
Lost connection while connected to a valid connection.
@ eConnectionStatusNoConnection
No connection.