130fdc8d8SChris Lattner //===-- RNBSocket.cpp -------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner // 1030fdc8d8SChris Lattner // Created by Greg Clayton on 12/12/07. 1130fdc8d8SChris Lattner // 1230fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 1330fdc8d8SChris Lattner 1430fdc8d8SChris Lattner #include "RNBSocket.h" 1595bf0fd3SGreg Clayton #include <arpa/inet.h> 1630fdc8d8SChris Lattner #include <errno.h> 1730fdc8d8SChris Lattner #include <fcntl.h> 1895bf0fd3SGreg Clayton #include <netdb.h> 1930fdc8d8SChris Lattner #include <netinet/in.h> 2030fdc8d8SChris Lattner #include <netinet/tcp.h> 2130fdc8d8SChris Lattner #include <termios.h> 2230fdc8d8SChris Lattner #include "DNBLog.h" 2330fdc8d8SChris Lattner #include "DNBError.h" 2430fdc8d8SChris Lattner 2542999a48SJason Molenda #ifdef WITH_LOCKDOWN 2630fdc8d8SChris Lattner #include "lockdown.h" 2730fdc8d8SChris Lattner #endif 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner /* Once we have a RNBSocket object with a port # specified, 3030fdc8d8SChris Lattner this function is called to wait for an incoming connection. 3130fdc8d8SChris Lattner This function blocks while waiting for that connection. */ 3230fdc8d8SChris Lattner 33fd23889eSGreg Clayton bool 34fd23889eSGreg Clayton ResolveIPV4HostName (const char *hostname, in_addr_t &addr) 35fd23889eSGreg Clayton { 36fd23889eSGreg Clayton if (hostname == NULL || 37fd23889eSGreg Clayton hostname[0] == '\0' || 38fd23889eSGreg Clayton strcmp(hostname, "localhost") == 0 || 39fd23889eSGreg Clayton strcmp(hostname, "127.0.0.1") == 0) 40fd23889eSGreg Clayton { 41fd23889eSGreg Clayton addr = htonl (INADDR_LOOPBACK); 42fd23889eSGreg Clayton return true; 43fd23889eSGreg Clayton } 44fd23889eSGreg Clayton else if (strcmp(hostname, "*") == 0) 45fd23889eSGreg Clayton { 46fd23889eSGreg Clayton addr = htonl (INADDR_ANY); 47fd23889eSGreg Clayton return true; 48fd23889eSGreg Clayton } 49fd23889eSGreg Clayton else 50fd23889eSGreg Clayton { 51fd23889eSGreg Clayton // See if an IP address was specified as numbers 52fd23889eSGreg Clayton int inet_pton_result = ::inet_pton (AF_INET, hostname, &addr); 53fd23889eSGreg Clayton 54fd23889eSGreg Clayton if (inet_pton_result == 1) 55fd23889eSGreg Clayton return true; 56fd23889eSGreg Clayton 57fd23889eSGreg Clayton struct hostent *host_entry = gethostbyname (hostname); 58fd23889eSGreg Clayton if (host_entry) 59fd23889eSGreg Clayton { 60fd23889eSGreg Clayton std::string ip_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); 61fd23889eSGreg Clayton inet_pton_result = ::inet_pton (AF_INET, ip_str.c_str(), &addr); 62fd23889eSGreg Clayton if (inet_pton_result == 1) 63fd23889eSGreg Clayton return true; 64fd23889eSGreg Clayton } 65fd23889eSGreg Clayton } 66fd23889eSGreg Clayton return false; 67fd23889eSGreg Clayton } 68fd23889eSGreg Clayton 6930fdc8d8SChris Lattner rnb_err_t 70*d629980aSGreg Clayton RNBSocket::Listen (const char *listen_host, uint16_t port, PortBoundCallback callback, const void *callback_baton) 7130fdc8d8SChris Lattner { 7230fdc8d8SChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 7330fdc8d8SChris Lattner // Disconnect without saving errno 7430fdc8d8SChris Lattner Disconnect (false); 7530fdc8d8SChris Lattner 76fd23889eSGreg Clayton // Now figure out the hostname that will be attaching and palce it into 77fd23889eSGreg Clayton struct sockaddr_in listen_addr; 78fd23889eSGreg Clayton ::memset (&listen_addr, 0, sizeof listen_addr); 79fd23889eSGreg Clayton listen_addr.sin_len = sizeof listen_addr; 80fd23889eSGreg Clayton listen_addr.sin_family = AF_INET; 81fd23889eSGreg Clayton listen_addr.sin_port = htons (port); 82fd23889eSGreg Clayton listen_addr.sin_addr.s_addr = INADDR_ANY; 83fd23889eSGreg Clayton 84fd23889eSGreg Clayton if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) 85fd23889eSGreg Clayton { 86fd23889eSGreg Clayton DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host); 87fd23889eSGreg Clayton return rnb_err; 88fd23889eSGreg Clayton } 89fd23889eSGreg Clayton 9030fdc8d8SChris Lattner DNBError err; 918b82f087SGreg Clayton int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 928b82f087SGreg Clayton if (listen_fd == -1) 9330fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 9430fdc8d8SChris Lattner 9530fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 968b82f087SGreg Clayton err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); 9730fdc8d8SChris Lattner 9830fdc8d8SChris Lattner if (err.Fail()) 9930fdc8d8SChris Lattner return rnb_err; 10030fdc8d8SChris Lattner 10130fdc8d8SChris Lattner // enable local address reuse 1028b82f087SGreg Clayton SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); 10330fdc8d8SChris Lattner 10430fdc8d8SChris Lattner struct sockaddr_in sa; 10530fdc8d8SChris Lattner ::memset (&sa, 0, sizeof sa); 10630fdc8d8SChris Lattner sa.sin_len = sizeof sa; 10730fdc8d8SChris Lattner sa.sin_family = AF_INET; 1088b82f087SGreg Clayton sa.sin_port = htons (port); 109fd23889eSGreg Clayton sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us) 1108b82f087SGreg Clayton int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); 11130fdc8d8SChris Lattner if (error == -1) 11230fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 11330fdc8d8SChris Lattner 11430fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 1158b82f087SGreg Clayton err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); 11630fdc8d8SChris Lattner 11730fdc8d8SChris Lattner if (err.Fail()) 11830fdc8d8SChris Lattner { 1198b82f087SGreg Clayton ClosePort (listen_fd, false); 12030fdc8d8SChris Lattner return rnb_err; 12130fdc8d8SChris Lattner } 12230fdc8d8SChris Lattner 123fd23889eSGreg Clayton error = ::listen (listen_fd, 5); 12430fdc8d8SChris Lattner if (error == -1) 12530fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 12630fdc8d8SChris Lattner 12730fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 1288b82f087SGreg Clayton err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); 12930fdc8d8SChris Lattner 13030fdc8d8SChris Lattner if (err.Fail()) 13130fdc8d8SChris Lattner { 1328b82f087SGreg Clayton ClosePort (listen_fd, false); 13330fdc8d8SChris Lattner return rnb_err; 13430fdc8d8SChris Lattner } 13530fdc8d8SChris Lattner 13691a9b247SGreg Clayton if (callback) 13791a9b247SGreg Clayton { 13891a9b247SGreg Clayton // We were asked to listen on port zero which means we 13991a9b247SGreg Clayton // must now read the actual port that was given to us 14091a9b247SGreg Clayton // as port zero is a special code for "find an open port 14191a9b247SGreg Clayton // for me". 14291a9b247SGreg Clayton if (port == 0) 14391a9b247SGreg Clayton { 14491a9b247SGreg Clayton socklen_t sa_len = sizeof (sa); 14591a9b247SGreg Clayton if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) 14691a9b247SGreg Clayton { 14791a9b247SGreg Clayton port = ntohs (sa.sin_port); 14891a9b247SGreg Clayton callback (callback_baton, port); 14991a9b247SGreg Clayton } 15091a9b247SGreg Clayton } 15191a9b247SGreg Clayton else 15291a9b247SGreg Clayton { 15391a9b247SGreg Clayton callback (callback_baton, port); 15491a9b247SGreg Clayton } 15591a9b247SGreg Clayton } 15691a9b247SGreg Clayton 157fd23889eSGreg Clayton struct sockaddr_in accept_addr; 158fd23889eSGreg Clayton ::memset (&accept_addr, 0, sizeof accept_addr); 159fd23889eSGreg Clayton accept_addr.sin_len = sizeof accept_addr; 160fd23889eSGreg Clayton 161fd23889eSGreg Clayton bool accept_connection = false; 162fd23889eSGreg Clayton 163fd23889eSGreg Clayton // Loop until we are happy with our connection 164fd23889eSGreg Clayton while (!accept_connection) 165fd23889eSGreg Clayton { 166fd23889eSGreg Clayton socklen_t accept_addr_len = sizeof accept_addr; 167fd23889eSGreg Clayton m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); 168fd23889eSGreg Clayton 1698b82f087SGreg Clayton if (m_fd == -1) 17030fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 17130fdc8d8SChris Lattner 17230fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 173fd23889eSGreg Clayton err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len); 174fd23889eSGreg Clayton 175fd23889eSGreg Clayton if (err.Fail()) 176fd23889eSGreg Clayton break; 177fd23889eSGreg Clayton 178fd23889eSGreg Clayton if (listen_addr.sin_addr.s_addr == INADDR_ANY) 179fd23889eSGreg Clayton accept_connection = true; 180fd23889eSGreg Clayton else 181fd23889eSGreg Clayton { 182fd23889eSGreg Clayton if (accept_addr_len == listen_addr.sin_len && 183fd23889eSGreg Clayton accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) 184fd23889eSGreg Clayton { 185fd23889eSGreg Clayton accept_connection = true; 186fd23889eSGreg Clayton } 187fd23889eSGreg Clayton else 188fd23889eSGreg Clayton { 189fd23889eSGreg Clayton ::close (m_fd); 190fd23889eSGreg Clayton m_fd = -1; 191fd23889eSGreg Clayton const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; 192fd23889eSGreg Clayton const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr; 193fd23889eSGreg Clayton ::fprintf (stderr, 194fd23889eSGreg Clayton "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", 195fd23889eSGreg Clayton accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], 196fd23889eSGreg Clayton listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); 197fd23889eSGreg Clayton DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)", 198fd23889eSGreg Clayton accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], 199fd23889eSGreg Clayton listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); 200fd23889eSGreg Clayton } 201fd23889eSGreg Clayton } 202fd23889eSGreg Clayton } 2038b82f087SGreg Clayton 2048b82f087SGreg Clayton ClosePort (listen_fd, false); 20530fdc8d8SChris Lattner 20630fdc8d8SChris Lattner if (err.Fail()) 20730fdc8d8SChris Lattner { 20830fdc8d8SChris Lattner return rnb_err; 20930fdc8d8SChris Lattner } 21030fdc8d8SChris Lattner else 21130fdc8d8SChris Lattner { 21230fdc8d8SChris Lattner // Keep our TCP packets coming without any delays. 2138b82f087SGreg Clayton SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 21430fdc8d8SChris Lattner } 21530fdc8d8SChris Lattner 21630fdc8d8SChris Lattner return rnb_success; 21730fdc8d8SChris Lattner } 21830fdc8d8SChris Lattner 21995bf0fd3SGreg Clayton rnb_err_t 22095bf0fd3SGreg Clayton RNBSocket::Connect (const char *host, uint16_t port) 22195bf0fd3SGreg Clayton { 22295bf0fd3SGreg Clayton Disconnect (false); 22395bf0fd3SGreg Clayton 22495bf0fd3SGreg Clayton // Create the socket 2258b82f087SGreg Clayton m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 2268b82f087SGreg Clayton if (m_fd == -1) 22795bf0fd3SGreg Clayton return rnb_err; 22895bf0fd3SGreg Clayton 22995bf0fd3SGreg Clayton // Enable local address reuse 2308b82f087SGreg Clayton SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); 23195bf0fd3SGreg Clayton 23295bf0fd3SGreg Clayton struct sockaddr_in sa; 23395bf0fd3SGreg Clayton ::memset (&sa, 0, sizeof (sa)); 23495bf0fd3SGreg Clayton sa.sin_family = AF_INET; 23595bf0fd3SGreg Clayton sa.sin_port = htons (port); 23695bf0fd3SGreg Clayton 237fd23889eSGreg Clayton if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) 23895bf0fd3SGreg Clayton { 239fd23889eSGreg Clayton DNBLogThreaded("error: failed to resolve host '%s'", host); 24095bf0fd3SGreg Clayton Disconnect (false); 24195bf0fd3SGreg Clayton return rnb_err; 24295bf0fd3SGreg Clayton } 24395bf0fd3SGreg Clayton 2448b82f087SGreg Clayton if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) 24595bf0fd3SGreg Clayton { 24695bf0fd3SGreg Clayton Disconnect (false); 24795bf0fd3SGreg Clayton return rnb_err; 24895bf0fd3SGreg Clayton } 24995bf0fd3SGreg Clayton 25095bf0fd3SGreg Clayton // Keep our TCP packets coming without any delays. 2518b82f087SGreg Clayton SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 25295bf0fd3SGreg Clayton return rnb_success; 25395bf0fd3SGreg Clayton } 25495bf0fd3SGreg Clayton 25542999a48SJason Molenda rnb_err_t 25642999a48SJason Molenda RNBSocket::useFD(int fd) 25742999a48SJason Molenda { 25842999a48SJason Molenda if (fd < 0) { 25942999a48SJason Molenda DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in."); 26042999a48SJason Molenda return rnb_err; 26142999a48SJason Molenda } 26242999a48SJason Molenda 26342999a48SJason Molenda m_fd = fd; 26442999a48SJason Molenda return rnb_success; 26542999a48SJason Molenda } 26642999a48SJason Molenda 26742999a48SJason Molenda #ifdef WITH_LOCKDOWN 26830fdc8d8SChris Lattner rnb_err_t 26930fdc8d8SChris Lattner RNBSocket::ConnectToService() 27030fdc8d8SChris Lattner { 27130fdc8d8SChris Lattner DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); 27230fdc8d8SChris Lattner // Disconnect from any previous connections 27330fdc8d8SChris Lattner Disconnect(false); 2747eaf54d8SJason Molenda if (::secure_lockdown_checkin (&m_ld_conn, NULL, NULL) != kLDESuccess) 27530fdc8d8SChris Lattner { 2767eaf54d8SJason Molenda DNBLogThreadedIf(LOG_RNB_COMM, "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed"); 27794379541SJason Molenda m_fd = -1; 27830fdc8d8SChris Lattner return rnb_not_connected; 27930fdc8d8SChris Lattner } 2807eaf54d8SJason Molenda m_fd = ::lockdown_get_socket (m_ld_conn); 2817eaf54d8SJason Molenda if (m_fd == -1) 2827eaf54d8SJason Molenda { 2837eaf54d8SJason Molenda DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed"); 2847eaf54d8SJason Molenda return rnb_not_connected; 2857eaf54d8SJason Molenda } 2868b82f087SGreg Clayton m_fd_from_lockdown = true; 28730fdc8d8SChris Lattner return rnb_success; 28830fdc8d8SChris Lattner } 28930fdc8d8SChris Lattner #endif 29030fdc8d8SChris Lattner 29130fdc8d8SChris Lattner rnb_err_t 29230fdc8d8SChris Lattner RNBSocket::OpenFile (const char *path) 29330fdc8d8SChris Lattner { 29430fdc8d8SChris Lattner DNBError err; 2958b82f087SGreg Clayton m_fd = open (path, O_RDWR); 2968b82f087SGreg Clayton if (m_fd == -1) 29730fdc8d8SChris Lattner { 29830fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 29930fdc8d8SChris Lattner err.LogThreaded ("can't open file '%s'", path); 30030fdc8d8SChris Lattner return rnb_not_connected; 30130fdc8d8SChris Lattner } 30230fdc8d8SChris Lattner else 30330fdc8d8SChris Lattner { 30430fdc8d8SChris Lattner struct termios stdin_termios; 30530fdc8d8SChris Lattner 3068b82f087SGreg Clayton if (::tcgetattr (m_fd, &stdin_termios) == 0) 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner stdin_termios.c_lflag &= ~ECHO; // Turn off echoing 30930fdc8d8SChris Lattner stdin_termios.c_lflag &= ~ICANON; // Get one char at a time 3108b82f087SGreg Clayton ::tcsetattr (m_fd, TCSANOW, &stdin_termios); 31130fdc8d8SChris Lattner } 31230fdc8d8SChris Lattner } 31330fdc8d8SChris Lattner return rnb_success; 31430fdc8d8SChris Lattner } 31530fdc8d8SChris Lattner 31630fdc8d8SChris Lattner int 31730fdc8d8SChris Lattner RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value) 31830fdc8d8SChris Lattner { 31930fdc8d8SChris Lattner return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); 32030fdc8d8SChris Lattner } 32130fdc8d8SChris Lattner 32230fdc8d8SChris Lattner rnb_err_t 32330fdc8d8SChris Lattner RNBSocket::Disconnect (bool save_errno) 32430fdc8d8SChris Lattner { 32542999a48SJason Molenda #ifdef WITH_LOCKDOWN 3268b82f087SGreg Clayton if (m_fd_from_lockdown) 3277eaf54d8SJason Molenda { 3288b82f087SGreg Clayton m_fd_from_lockdown = false; 3297eaf54d8SJason Molenda m_fd = -1; 3302d512bcaSJim Ingham lockdown_disconnect (m_ld_conn); 3317eaf54d8SJason Molenda return rnb_success; 3327eaf54d8SJason Molenda } 33342999a48SJason Molenda #endif 3348b82f087SGreg Clayton return ClosePort (m_fd, save_errno); 33530fdc8d8SChris Lattner } 33630fdc8d8SChris Lattner 33730fdc8d8SChris Lattner 33830fdc8d8SChris Lattner rnb_err_t 33930fdc8d8SChris Lattner RNBSocket::Read (std::string &p) 34030fdc8d8SChris Lattner { 34130fdc8d8SChris Lattner char buf[1024]; 34230fdc8d8SChris Lattner p.clear(); 34330fdc8d8SChris Lattner 34430fdc8d8SChris Lattner // Note that BUF is on the stack so we must be careful to keep any 34530fdc8d8SChris Lattner // writes to BUF from overflowing or we'll have security issues. 34630fdc8d8SChris Lattner 3478b82f087SGreg Clayton if (m_fd == -1) 34830fdc8d8SChris Lattner return rnb_err; 34930fdc8d8SChris Lattner 35030fdc8d8SChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 35130fdc8d8SChris Lattner DNBError err; 3528b82f087SGreg Clayton int bytesread = read (m_fd, buf, sizeof (buf)); 35330fdc8d8SChris Lattner if (bytesread <= 0) 35430fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 35530fdc8d8SChris Lattner else 35630fdc8d8SChris Lattner p.append(buf, bytesread); 35730fdc8d8SChris Lattner 35830fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 35943e0af06SGreg Clayton err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof (buf), (uint64_t)bytesread); 36030fdc8d8SChris Lattner 36130fdc8d8SChris Lattner // Our port went away - we have to mark this so IsConnected will return the truth. 36230fdc8d8SChris Lattner if (bytesread == 0) 36330fdc8d8SChris Lattner { 3648b82f087SGreg Clayton m_fd = -1; 36530fdc8d8SChris Lattner return rnb_not_connected; 36630fdc8d8SChris Lattner } 36730fdc8d8SChris Lattner else if (bytesread == -1) 36830fdc8d8SChris Lattner { 3698b82f087SGreg Clayton m_fd = -1; 37030fdc8d8SChris Lattner return rnb_err; 37130fdc8d8SChris Lattner } 37230fdc8d8SChris Lattner // Strip spaces from the end of the buffer 37330fdc8d8SChris Lattner while (!p.empty() && isspace (p[p.size() - 1])) 37430fdc8d8SChris Lattner p.erase (p.size () - 1); 37530fdc8d8SChris Lattner 37630fdc8d8SChris Lattner // Most data in the debugserver packets valid printable characters... 37730fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); 37830fdc8d8SChris Lattner return rnb_success; 37930fdc8d8SChris Lattner } 38030fdc8d8SChris Lattner 38130fdc8d8SChris Lattner rnb_err_t 38230fdc8d8SChris Lattner RNBSocket::Write (const void *buffer, size_t length) 38330fdc8d8SChris Lattner { 3848b82f087SGreg Clayton if (m_fd == -1) 38530fdc8d8SChris Lattner return rnb_err; 38630fdc8d8SChris Lattner 38730fdc8d8SChris Lattner DNBError err; 38842999a48SJason Molenda int bytessent = write (m_fd, buffer, length); 38930fdc8d8SChris Lattner if (bytessent < 0) 39030fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 39130fdc8d8SChris Lattner 39230fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 39343e0af06SGreg Clayton err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", m_fd, buffer, length, (uint64_t)bytessent); 39430fdc8d8SChris Lattner 39530fdc8d8SChris Lattner if (bytessent < 0) 39630fdc8d8SChris Lattner return rnb_err; 39730fdc8d8SChris Lattner 39830fdc8d8SChris Lattner if (bytessent != length) 39930fdc8d8SChris Lattner return rnb_err; 40030fdc8d8SChris Lattner 401490fbbe2SGreg Clayton DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", (int)length, (char *)buffer); // All data is string based in debugserver, so this is safe 402490fbbe2SGreg Clayton DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer); 40330fdc8d8SChris Lattner 40430fdc8d8SChris Lattner return rnb_success; 40530fdc8d8SChris Lattner } 40630fdc8d8SChris Lattner 40730fdc8d8SChris Lattner 40830fdc8d8SChris Lattner rnb_err_t 40930fdc8d8SChris Lattner RNBSocket::ClosePort (int& fd, bool save_errno) 41030fdc8d8SChris Lattner { 41130fdc8d8SChris Lattner int close_err = 0; 41230fdc8d8SChris Lattner if (fd > 0) 41330fdc8d8SChris Lattner { 41430fdc8d8SChris Lattner errno = 0; 41530fdc8d8SChris Lattner close_err = close (fd); 41630fdc8d8SChris Lattner fd = -1; 41730fdc8d8SChris Lattner } 41830fdc8d8SChris Lattner return close_err != 0 ? rnb_err : rnb_success; 41930fdc8d8SChris Lattner } 42030fdc8d8SChris Lattner 42130fdc8d8SChris Lattner 422