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 2530fdc8d8SChris Lattner #if defined (__arm__) 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 3330fdc8d8SChris Lattner rnb_err_t 348b82f087SGreg Clayton RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callback_baton) 3530fdc8d8SChris Lattner { 3630fdc8d8SChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 3730fdc8d8SChris Lattner // Disconnect without saving errno 3830fdc8d8SChris Lattner Disconnect (false); 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner DNBError err; 418b82f087SGreg Clayton int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 428b82f087SGreg Clayton if (listen_fd == -1) 4330fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 4430fdc8d8SChris Lattner 4530fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 468b82f087SGreg Clayton err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); 4730fdc8d8SChris Lattner 4830fdc8d8SChris Lattner if (err.Fail()) 4930fdc8d8SChris Lattner return rnb_err; 5030fdc8d8SChris Lattner 5130fdc8d8SChris Lattner // enable local address reuse 528b82f087SGreg Clayton SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner struct sockaddr_in sa; 5530fdc8d8SChris Lattner ::memset (&sa, 0, sizeof sa); 5630fdc8d8SChris Lattner sa.sin_len = sizeof sa; 5730fdc8d8SChris Lattner sa.sin_family = AF_INET; 588b82f087SGreg Clayton sa.sin_port = htons (port); 5930fdc8d8SChris Lattner sa.sin_addr.s_addr = htonl (INADDR_ANY); 6030fdc8d8SChris Lattner 618b82f087SGreg Clayton int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); 6230fdc8d8SChris Lattner if (error == -1) 6330fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 6430fdc8d8SChris Lattner 6530fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 668b82f087SGreg Clayton err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); 6730fdc8d8SChris Lattner 6830fdc8d8SChris Lattner if (err.Fail()) 6930fdc8d8SChris Lattner { 708b82f087SGreg Clayton ClosePort (listen_fd, false); 7130fdc8d8SChris Lattner return rnb_err; 7230fdc8d8SChris Lattner } 7330fdc8d8SChris Lattner 748b82f087SGreg Clayton if (callback && port == 0) 758b82f087SGreg Clayton { 768b82f087SGreg Clayton // We were asked to listen on port zero which means we 778b82f087SGreg Clayton // must now read the actual port that was given to us 788b82f087SGreg Clayton // as port zero is a special code for "find an open port 798b82f087SGreg Clayton // for me". 808b82f087SGreg Clayton socklen_t sa_len = sizeof (sa); 818b82f087SGreg Clayton if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) 828b82f087SGreg Clayton { 838b82f087SGreg Clayton port = ntohs (sa.sin_port); 848b82f087SGreg Clayton callback (callback_baton, port); 858b82f087SGreg Clayton } 868b82f087SGreg Clayton } 878b82f087SGreg Clayton 888b82f087SGreg Clayton error = ::listen (listen_fd, 1); 8930fdc8d8SChris Lattner if (error == -1) 9030fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 9130fdc8d8SChris Lattner 9230fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 938b82f087SGreg Clayton err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); 9430fdc8d8SChris Lattner 9530fdc8d8SChris Lattner if (err.Fail()) 9630fdc8d8SChris Lattner { 978b82f087SGreg Clayton ClosePort (listen_fd, false); 9830fdc8d8SChris Lattner return rnb_err; 9930fdc8d8SChris Lattner } 10030fdc8d8SChris Lattner 1018b82f087SGreg Clayton m_fd = ::accept (listen_fd, NULL, 0); 1028b82f087SGreg Clayton if (m_fd == -1) 10330fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 10430fdc8d8SChris Lattner 10530fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 1068b82f087SGreg Clayton err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_fd); 1078b82f087SGreg Clayton 1088b82f087SGreg Clayton ClosePort (listen_fd, false); 10930fdc8d8SChris Lattner 11030fdc8d8SChris Lattner if (err.Fail()) 11130fdc8d8SChris Lattner { 11230fdc8d8SChris Lattner return rnb_err; 11330fdc8d8SChris Lattner } 11430fdc8d8SChris Lattner else 11530fdc8d8SChris Lattner { 11630fdc8d8SChris Lattner // Keep our TCP packets coming without any delays. 1178b82f087SGreg Clayton SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 11830fdc8d8SChris Lattner } 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner return rnb_success; 12130fdc8d8SChris Lattner } 12230fdc8d8SChris Lattner 12395bf0fd3SGreg Clayton rnb_err_t 12495bf0fd3SGreg Clayton RNBSocket::Connect (const char *host, uint16_t port) 12595bf0fd3SGreg Clayton { 12695bf0fd3SGreg Clayton Disconnect (false); 12795bf0fd3SGreg Clayton 12895bf0fd3SGreg Clayton // Create the socket 1298b82f087SGreg Clayton m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); 1308b82f087SGreg Clayton if (m_fd == -1) 13195bf0fd3SGreg Clayton return rnb_err; 13295bf0fd3SGreg Clayton 13395bf0fd3SGreg Clayton // Enable local address reuse 1348b82f087SGreg Clayton SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); 13595bf0fd3SGreg Clayton 13695bf0fd3SGreg Clayton struct sockaddr_in sa; 13795bf0fd3SGreg Clayton ::memset (&sa, 0, sizeof (sa)); 13895bf0fd3SGreg Clayton sa.sin_family = AF_INET; 13995bf0fd3SGreg Clayton sa.sin_port = htons (port); 14095bf0fd3SGreg Clayton 14195bf0fd3SGreg Clayton if (host == NULL) 14295bf0fd3SGreg Clayton host = "localhost"; 14395bf0fd3SGreg Clayton 14495bf0fd3SGreg Clayton int inet_pton_result = ::inet_pton (AF_INET, host, &sa.sin_addr); 14595bf0fd3SGreg Clayton 14695bf0fd3SGreg Clayton if (inet_pton_result <= 0) 14795bf0fd3SGreg Clayton { 14895bf0fd3SGreg Clayton struct hostent *host_entry = gethostbyname (host); 14995bf0fd3SGreg Clayton if (host_entry) 15095bf0fd3SGreg Clayton { 15195bf0fd3SGreg Clayton std::string host_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); 15295bf0fd3SGreg Clayton inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); 15395bf0fd3SGreg Clayton if (inet_pton_result <= 0) 15495bf0fd3SGreg Clayton { 15595bf0fd3SGreg Clayton Disconnect (false); 15695bf0fd3SGreg Clayton return rnb_err; 15795bf0fd3SGreg Clayton } 15895bf0fd3SGreg Clayton } 15995bf0fd3SGreg Clayton } 16095bf0fd3SGreg Clayton 1618b82f087SGreg Clayton if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) 16295bf0fd3SGreg Clayton { 16395bf0fd3SGreg Clayton Disconnect (false); 16495bf0fd3SGreg Clayton return rnb_err; 16595bf0fd3SGreg Clayton } 16695bf0fd3SGreg Clayton 16795bf0fd3SGreg Clayton // Keep our TCP packets coming without any delays. 1688b82f087SGreg Clayton SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); 16995bf0fd3SGreg Clayton return rnb_success; 17095bf0fd3SGreg Clayton } 17195bf0fd3SGreg Clayton 17230fdc8d8SChris Lattner #if defined (__arm__) 17330fdc8d8SChris Lattner rnb_err_t 17430fdc8d8SChris Lattner RNBSocket::ConnectToService() 17530fdc8d8SChris Lattner { 17630fdc8d8SChris Lattner DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); 17730fdc8d8SChris Lattner // Disconnect from any previous connections 17830fdc8d8SChris Lattner Disconnect(false); 17930fdc8d8SChris Lattner 1808b82f087SGreg Clayton m_fd = ::lockdown_checkin (NULL, NULL); 1818b82f087SGreg Clayton if (m_fd == -1) 18230fdc8d8SChris Lattner { 18330fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_checkin(NULL, NULL) failed"); 18430fdc8d8SChris Lattner return rnb_not_connected; 18530fdc8d8SChris Lattner } 1868b82f087SGreg Clayton m_fd_from_lockdown = true; 18730fdc8d8SChris Lattner return rnb_success; 18830fdc8d8SChris Lattner } 18930fdc8d8SChris Lattner #endif 19030fdc8d8SChris Lattner 19130fdc8d8SChris Lattner rnb_err_t 19230fdc8d8SChris Lattner RNBSocket::OpenFile (const char *path) 19330fdc8d8SChris Lattner { 19430fdc8d8SChris Lattner DNBError err; 1958b82f087SGreg Clayton m_fd = open (path, O_RDWR); 1968b82f087SGreg Clayton if (m_fd == -1) 19730fdc8d8SChris Lattner { 19830fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 19930fdc8d8SChris Lattner err.LogThreaded ("can't open file '%s'", path); 20030fdc8d8SChris Lattner return rnb_not_connected; 20130fdc8d8SChris Lattner } 20230fdc8d8SChris Lattner else 20330fdc8d8SChris Lattner { 20430fdc8d8SChris Lattner struct termios stdin_termios; 20530fdc8d8SChris Lattner 2068b82f087SGreg Clayton if (::tcgetattr (m_fd, &stdin_termios) == 0) 20730fdc8d8SChris Lattner { 20830fdc8d8SChris Lattner stdin_termios.c_lflag &= ~ECHO; // Turn off echoing 20930fdc8d8SChris Lattner stdin_termios.c_lflag &= ~ICANON; // Get one char at a time 2108b82f087SGreg Clayton ::tcsetattr (m_fd, TCSANOW, &stdin_termios); 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner return rnb_success; 21430fdc8d8SChris Lattner } 21530fdc8d8SChris Lattner 21630fdc8d8SChris Lattner int 21730fdc8d8SChris Lattner RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value) 21830fdc8d8SChris Lattner { 21930fdc8d8SChris Lattner return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); 22030fdc8d8SChris Lattner } 22130fdc8d8SChris Lattner 22230fdc8d8SChris Lattner rnb_err_t 22330fdc8d8SChris Lattner RNBSocket::Disconnect (bool save_errno) 22430fdc8d8SChris Lattner { 2258b82f087SGreg Clayton if (m_fd_from_lockdown) 2268b82f087SGreg Clayton m_fd_from_lockdown = false; 2278b82f087SGreg Clayton return ClosePort (m_fd, save_errno); 22830fdc8d8SChris Lattner } 22930fdc8d8SChris Lattner 23030fdc8d8SChris Lattner 23130fdc8d8SChris Lattner rnb_err_t 23230fdc8d8SChris Lattner RNBSocket::Read (std::string &p) 23330fdc8d8SChris Lattner { 23430fdc8d8SChris Lattner char buf[1024]; 23530fdc8d8SChris Lattner p.clear(); 23630fdc8d8SChris Lattner 23730fdc8d8SChris Lattner // Note that BUF is on the stack so we must be careful to keep any 23830fdc8d8SChris Lattner // writes to BUF from overflowing or we'll have security issues. 23930fdc8d8SChris Lattner 2408b82f087SGreg Clayton if (m_fd == -1) 24130fdc8d8SChris Lattner return rnb_err; 24230fdc8d8SChris Lattner 24330fdc8d8SChris Lattner //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); 24430fdc8d8SChris Lattner DNBError err; 2458b82f087SGreg Clayton int bytesread = read (m_fd, buf, sizeof (buf)); 24630fdc8d8SChris Lattner if (bytesread <= 0) 24730fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 24830fdc8d8SChris Lattner else 24930fdc8d8SChris Lattner p.append(buf, bytesread); 25030fdc8d8SChris Lattner 25130fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 2528b82f087SGreg Clayton err.LogThreaded("::read ( %i, %p, %zu ) => %i", m_fd, buf, sizeof (buf), bytesread); 25330fdc8d8SChris Lattner 25430fdc8d8SChris Lattner // Our port went away - we have to mark this so IsConnected will return the truth. 25530fdc8d8SChris Lattner if (bytesread == 0) 25630fdc8d8SChris Lattner { 2578b82f087SGreg Clayton m_fd = -1; 25830fdc8d8SChris Lattner return rnb_not_connected; 25930fdc8d8SChris Lattner } 26030fdc8d8SChris Lattner else if (bytesread == -1) 26130fdc8d8SChris Lattner { 2628b82f087SGreg Clayton m_fd = -1; 26330fdc8d8SChris Lattner return rnb_err; 26430fdc8d8SChris Lattner } 26530fdc8d8SChris Lattner // Strip spaces from the end of the buffer 26630fdc8d8SChris Lattner while (!p.empty() && isspace (p[p.size() - 1])) 26730fdc8d8SChris Lattner p.erase (p.size () - 1); 26830fdc8d8SChris Lattner 26930fdc8d8SChris Lattner // Most data in the debugserver packets valid printable characters... 27030fdc8d8SChris Lattner DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); 27130fdc8d8SChris Lattner return rnb_success; 27230fdc8d8SChris Lattner } 27330fdc8d8SChris Lattner 27430fdc8d8SChris Lattner rnb_err_t 27530fdc8d8SChris Lattner RNBSocket::Write (const void *buffer, size_t length) 27630fdc8d8SChris Lattner { 2778b82f087SGreg Clayton if (m_fd == -1) 27830fdc8d8SChris Lattner return rnb_err; 27930fdc8d8SChris Lattner 28030fdc8d8SChris Lattner DNBError err; 2818b82f087SGreg Clayton int bytessent = send (m_fd, buffer, length, 0); 28230fdc8d8SChris Lattner if (bytessent < 0) 28330fdc8d8SChris Lattner err.SetError(errno, DNBError::POSIX); 28430fdc8d8SChris Lattner 28530fdc8d8SChris Lattner if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) 2868b82f087SGreg Clayton err.LogThreaded("::send ( socket = %i, buffer = %p, length = %zu, flags = 0 ) => %i", m_fd, buffer, length, bytessent); 28730fdc8d8SChris Lattner 28830fdc8d8SChris Lattner if (bytessent < 0) 28930fdc8d8SChris Lattner return rnb_err; 29030fdc8d8SChris Lattner 29130fdc8d8SChris Lattner if (bytessent != length) 29230fdc8d8SChris Lattner return rnb_err; 29330fdc8d8SChris Lattner 294*490fbbe2SGreg Clayton DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", (int)length, (char *)buffer); // All data is string based in debugserver, so this is safe 295*490fbbe2SGreg Clayton DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer); 29630fdc8d8SChris Lattner 29730fdc8d8SChris Lattner return rnb_success; 29830fdc8d8SChris Lattner } 29930fdc8d8SChris Lattner 30030fdc8d8SChris Lattner 30130fdc8d8SChris Lattner rnb_err_t 30230fdc8d8SChris Lattner RNBSocket::ClosePort (int& fd, bool save_errno) 30330fdc8d8SChris Lattner { 30430fdc8d8SChris Lattner int close_err = 0; 30530fdc8d8SChris Lattner if (fd > 0) 30630fdc8d8SChris Lattner { 30730fdc8d8SChris Lattner errno = 0; 30830fdc8d8SChris Lattner close_err = close (fd); 30930fdc8d8SChris Lattner fd = -1; 31030fdc8d8SChris Lattner } 31130fdc8d8SChris Lattner return close_err != 0 ? rnb_err : rnb_success; 31230fdc8d8SChris Lattner } 31330fdc8d8SChris Lattner 31430fdc8d8SChris Lattner 315