From: Igor Kulaychuk Date: Wed, 11 Apr 2018 17:34:24 +0000 (+0300) Subject: Add option for listening requests on the TCP/IP port instead of stdin/out X-Git-Tag: submit/tizen/20180620.071641~7^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a3527adc33ac8a759b3e8effb70e6d37c5c99613;p=sdk%2Ftools%2Fnetcoredbg.git Add option for listening requests on the TCP/IP port instead of stdin/out --- diff --git a/src/debug/netcoredbg/main.cpp b/src/debug/netcoredbg/main.cpp index 919b49e..8bd8135 100644 --- a/src/debug/netcoredbg/main.cpp +++ b/src/debug/netcoredbg/main.cpp @@ -12,6 +12,7 @@ #include "miprotocol.h" #include "vscodeprotocol.h" +static const uint16_t DEFAULT_SERVER_PORT = 4711; static void print_help() { @@ -24,6 +25,10 @@ static void print_help() "--interpreter=vscode Puts the debugger into VS Code Debugger mode.\n" "--engineLogging[=] Enable logging to VsDbg-UI or file for the engine.\n" " Only supported by the VsCode interpreter.\n" + "--server[=port_num] Start the debugger listening for requests on the\n" + " specified TCP/IP port instead of stdin/out. If port is not specified\n" + " TCP %i will be used.\n", + (int)DEFAULT_SERVER_PORT ); } @@ -40,6 +45,8 @@ int main(int argc, char *argv[]) bool engineLogging = false; std::string logFilePath; + uint16_t serverPort = 0; + for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--attach") == 0) @@ -84,6 +91,22 @@ int main(int argc, char *argv[]) print_help(); return EXIT_SUCCESS; } + else if (strcmp(argv[i], "--server") == 0) + { + serverPort = DEFAULT_SERVER_PORT; + continue; + } + else if (strstr(argv[i], "--server=") == argv[i]) + { + char *err; + serverPort = strtoul(argv[i] + strlen("--server="), &err, 10); + if (*err != 0) + { + fprintf(stderr, "Error: Missing process id\n"); + return EXIT_FAILURE; + } + continue; + } else { fprintf(stderr, "Error: Unknown option %s\n", argv[i]); @@ -91,6 +114,7 @@ int main(int argc, char *argv[]) } } + IORedirectServer server(serverPort); ManagedDebugger debugger; std::unique_ptr protocol; diff --git a/src/debug/netcoredbg/platform.cpp b/src/debug/netcoredbg/platform.cpp index b48ef6e..1482f1d 100644 --- a/src/debug/netcoredbg/platform.cpp +++ b/src/debug/netcoredbg/platform.cpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #if defined(__APPLE__) #include @@ -182,3 +185,155 @@ void *DLSym(void *handle, const std::string &name) { return dlsym(handle, name.c_str()); } + +// From https://stackoverflow.com/questions/13541313/handle-socket-descriptors-like-file-descriptor-fstream-c-linux +class fdbuf : public std::streambuf +{ +private: + enum { bufsize = 1024 }; + char outbuf_[bufsize]; + char inbuf_[bufsize + 16 - sizeof(int)]; + int fd_; +public: + typedef std::streambuf::traits_type traits_type; + + fdbuf(int fd); + ~fdbuf(); + void open(int fd); + void close(); + +protected: + int overflow(int c); + int underflow(); + int sync(); +}; + +fdbuf::fdbuf(int fd) + : fd_(-1) { + this->open(fd); +} + +fdbuf::~fdbuf() { + this->close(); +} + +void fdbuf::open(int fd) { + this->close(); + this->fd_ = fd; + this->setg(this->inbuf_, this->inbuf_, this->inbuf_); + this->setp(this->outbuf_, this->outbuf_ + bufsize - 1); +} + +void fdbuf::close() { + if (!(this->fd_ < 0)) { + this->sync(); + ::close(this->fd_); + } +} + +int fdbuf::overflow(int c) { + if (!traits_type::eq_int_type(c, traits_type::eof())) { + *this->pptr() = traits_type::to_char_type(c); + this->pbump(1); + } + return this->sync() == -1 + ? traits_type::eof() + : traits_type::not_eof(c); +} + +int fdbuf::sync() { + if (this->pbase() != this->pptr()) { + std::streamsize size(this->pptr() - this->pbase()); + std::streamsize done(::write(this->fd_, this->outbuf_, size)); + // The code below assumes that it is success if the stream made + // some progress. Depending on the needs it may be more + // reasonable to consider it a success only if it managed to + // write the entire buffer and, e.g., loop a couple of times + // to try achieving this success. + if (0 < done) { + std::copy(this->pbase() + done, this->pptr(), this->pbase()); + this->setp(this->pbase(), this->epptr()); + this->pbump(size - done); + } + } + return this->pptr() != this->epptr()? 0: -1; +} + +int fdbuf::underflow() +{ + if (this->gptr() == this->egptr()) { + std::streamsize pback(std::min(this->gptr() - this->eback(), + std::ptrdiff_t(16 - sizeof(int)))); + std::copy(this->egptr() - pback, this->egptr(), this->eback()); + int done(::read(this->fd_, this->eback() + pback, bufsize)); + this->setg(this->eback(), + this->eback() + pback, + this->eback() + pback + std::max(0, done)); + } + return this->gptr() == this->egptr() + ? traits_type::eof() + : traits_type::to_int_type(*this->gptr()); +} + +IORedirectServer::IORedirectServer(uint16_t port) : m_in(nullptr), m_out(nullptr), m_sockfd(-1) +{ + int newsockfd; + socklen_t clilen; + struct sockaddr_in serv_addr, cli_addr; + int n; + + m_prevIn = std::cin.rdbuf(); + m_prevOut = std::cout.rdbuf(); + + if (port == 0) + return; + + m_sockfd = ::socket(AF_INET, SOCK_STREAM, 0); + if (m_sockfd < 0) + return; + + int enable = 1; + if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) + { + ::close(m_sockfd); + m_sockfd = -1; + return; + } + memset(&serv_addr, 0, sizeof(serv_addr)); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(port); + + if (::bind(m_sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + ::close(m_sockfd); + m_sockfd = -1; + return; + } + + ::listen(m_sockfd, 5); + clilen = sizeof(cli_addr); + newsockfd = ::accept(m_sockfd, (struct sockaddr *) &cli_addr, &clilen); + if (newsockfd < 0) + { + ::close(m_sockfd); + m_sockfd = -1; + return; + } + + m_in = new fdbuf(newsockfd); + m_out = new fdbuf(newsockfd); + + std::cin.rdbuf(m_in); + std::cout.rdbuf(m_out); +} + +IORedirectServer::~IORedirectServer() +{ + std::cin.rdbuf(m_prevIn); + std::cout.rdbuf(m_prevOut); + delete m_in; + delete m_out; + ::close(m_sockfd); +} diff --git a/src/debug/netcoredbg/platform.h b/src/debug/netcoredbg/platform.h index ee84cc0..801bf4f 100644 --- a/src/debug/netcoredbg/platform.h +++ b/src/debug/netcoredbg/platform.h @@ -4,6 +4,7 @@ #pragma once #include +#include unsigned long OSPageSize(); void AddFilesFromDirectoryToTpaList(const std::string &directory, std::string &tpaList); @@ -13,3 +14,16 @@ bool SetWorkDir(const std::string &path); void USleep(uint32_t duration); void *DLOpen(const std::string &path); void *DLSym(void *handle, const std::string &name); + +class IORedirectServer +{ + std::streambuf *m_in; + std::streambuf *m_out; + std::streambuf *m_prevIn; + std::streambuf *m_prevOut; + int m_sockfd; +public: + IORedirectServer(uint16_t port); + ~IORedirectServer(); + operator bool() const { return m_sockfd != -1; } +};