1*30fdc8d8SChris Lattner //===-- RNBSocket.cpp -------------------------------------------*- C++ -*-===//
2*30fdc8d8SChris Lattner //
3*30fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
4*30fdc8d8SChris Lattner //
5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
7*30fdc8d8SChris Lattner //
8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
9*30fdc8d8SChris Lattner //
10*30fdc8d8SChris Lattner //  Created by Greg Clayton on 12/12/07.
11*30fdc8d8SChris Lattner //
12*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
13*30fdc8d8SChris Lattner 
14*30fdc8d8SChris Lattner #include "RNBSocket.h"
15*30fdc8d8SChris Lattner #include <errno.h>
16*30fdc8d8SChris Lattner #include <fcntl.h>
17*30fdc8d8SChris Lattner #include <netinet/in.h>
18*30fdc8d8SChris Lattner #include <netinet/tcp.h>
19*30fdc8d8SChris Lattner #include <termios.h>
20*30fdc8d8SChris Lattner #include "DNBLog.h"
21*30fdc8d8SChris Lattner #include "DNBError.h"
22*30fdc8d8SChris Lattner 
23*30fdc8d8SChris Lattner #if defined (__arm__)
24*30fdc8d8SChris Lattner #include "lockdown.h"
25*30fdc8d8SChris Lattner #endif
26*30fdc8d8SChris Lattner 
27*30fdc8d8SChris Lattner /* Once we have a RNBSocket object with a port # specified,
28*30fdc8d8SChris Lattner    this function is called to wait for an incoming connection.
29*30fdc8d8SChris Lattner    This function blocks while waiting for that connection.  */
30*30fdc8d8SChris Lattner 
31*30fdc8d8SChris Lattner rnb_err_t
32*30fdc8d8SChris Lattner RNBSocket::Listen (in_port_t listen_port_num)
33*30fdc8d8SChris Lattner {
34*30fdc8d8SChris Lattner     //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
35*30fdc8d8SChris Lattner     // Disconnect without saving errno
36*30fdc8d8SChris Lattner     Disconnect (false);
37*30fdc8d8SChris Lattner 
38*30fdc8d8SChris Lattner     DNBError err;
39*30fdc8d8SChris Lattner     int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
40*30fdc8d8SChris Lattner     if (listen_port == -1)
41*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
42*30fdc8d8SChris Lattner 
43*30fdc8d8SChris Lattner     if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
44*30fdc8d8SChris Lattner         err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_port);
45*30fdc8d8SChris Lattner 
46*30fdc8d8SChris Lattner     if (err.Fail())
47*30fdc8d8SChris Lattner         return rnb_err;
48*30fdc8d8SChris Lattner 
49*30fdc8d8SChris Lattner     // enable local address reuse
50*30fdc8d8SChris Lattner     SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1);
51*30fdc8d8SChris Lattner 
52*30fdc8d8SChris Lattner     struct sockaddr_in sa;
53*30fdc8d8SChris Lattner     ::memset (&sa, 0, sizeof sa);
54*30fdc8d8SChris Lattner     sa.sin_len = sizeof sa;
55*30fdc8d8SChris Lattner     sa.sin_family = AF_INET;
56*30fdc8d8SChris Lattner     sa.sin_port = htons (listen_port_num);
57*30fdc8d8SChris Lattner     sa.sin_addr.s_addr = htonl (INADDR_ANY);
58*30fdc8d8SChris Lattner 
59*30fdc8d8SChris Lattner     int error = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa));
60*30fdc8d8SChris Lattner     if (error == -1)
61*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
62*30fdc8d8SChris Lattner 
63*30fdc8d8SChris Lattner     if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
64*30fdc8d8SChris Lattner         err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_port);
65*30fdc8d8SChris Lattner 
66*30fdc8d8SChris Lattner     if (err.Fail())
67*30fdc8d8SChris Lattner     {
68*30fdc8d8SChris Lattner         ClosePort (listen_port, false);
69*30fdc8d8SChris Lattner         return rnb_err;
70*30fdc8d8SChris Lattner     }
71*30fdc8d8SChris Lattner 
72*30fdc8d8SChris Lattner     error = ::listen (listen_port, 1);
73*30fdc8d8SChris Lattner     if (error == -1)
74*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
75*30fdc8d8SChris Lattner 
76*30fdc8d8SChris Lattner     if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
77*30fdc8d8SChris Lattner         err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_port);
78*30fdc8d8SChris Lattner 
79*30fdc8d8SChris Lattner     if (err.Fail())
80*30fdc8d8SChris Lattner     {
81*30fdc8d8SChris Lattner         ClosePort (listen_port, false);
82*30fdc8d8SChris Lattner         return rnb_err;
83*30fdc8d8SChris Lattner     }
84*30fdc8d8SChris Lattner 
85*30fdc8d8SChris Lattner     m_conn_port = ::accept (listen_port, NULL, 0);
86*30fdc8d8SChris Lattner     if (m_conn_port == -1)
87*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
88*30fdc8d8SChris Lattner 
89*30fdc8d8SChris Lattner     if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
90*30fdc8d8SChris Lattner         err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_port);
91*30fdc8d8SChris Lattner 
92*30fdc8d8SChris Lattner     if (err.Fail())
93*30fdc8d8SChris Lattner     {
94*30fdc8d8SChris Lattner         ClosePort (listen_port, false);
95*30fdc8d8SChris Lattner         return rnb_err;
96*30fdc8d8SChris Lattner     }
97*30fdc8d8SChris Lattner     else
98*30fdc8d8SChris Lattner     {
99*30fdc8d8SChris Lattner         // We are done with the listen port
100*30fdc8d8SChris Lattner         ClosePort (listen_port, false);
101*30fdc8d8SChris Lattner 
102*30fdc8d8SChris Lattner         // Keep our TCP packets coming without any delays.
103*30fdc8d8SChris Lattner         SetSocketOption (m_conn_port, IPPROTO_TCP, TCP_NODELAY, 1);
104*30fdc8d8SChris Lattner     }
105*30fdc8d8SChris Lattner 
106*30fdc8d8SChris Lattner     return rnb_success;
107*30fdc8d8SChris Lattner }
108*30fdc8d8SChris Lattner 
109*30fdc8d8SChris Lattner #if defined (__arm__)
110*30fdc8d8SChris Lattner rnb_err_t
111*30fdc8d8SChris Lattner RNBSocket::ConnectToService()
112*30fdc8d8SChris Lattner {
113*30fdc8d8SChris Lattner     DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME);
114*30fdc8d8SChris Lattner     // Disconnect from any previous connections
115*30fdc8d8SChris Lattner     Disconnect(false);
116*30fdc8d8SChris Lattner 
117*30fdc8d8SChris Lattner     m_conn_port = ::lockdown_checkin (NULL, NULL);
118*30fdc8d8SChris Lattner     if (m_conn_port == -1)
119*30fdc8d8SChris Lattner     {
120*30fdc8d8SChris Lattner         DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_checkin(NULL, NULL) failed");
121*30fdc8d8SChris Lattner         return rnb_not_connected;
122*30fdc8d8SChris Lattner     }
123*30fdc8d8SChris Lattner     m_conn_port_from_lockdown = true;
124*30fdc8d8SChris Lattner     return rnb_success;
125*30fdc8d8SChris Lattner }
126*30fdc8d8SChris Lattner #endif
127*30fdc8d8SChris Lattner 
128*30fdc8d8SChris Lattner rnb_err_t
129*30fdc8d8SChris Lattner RNBSocket::OpenFile (const char *path)
130*30fdc8d8SChris Lattner {
131*30fdc8d8SChris Lattner     DNBError err;
132*30fdc8d8SChris Lattner     m_conn_port = open (path, O_RDWR);
133*30fdc8d8SChris Lattner     if (m_conn_port == -1)
134*30fdc8d8SChris Lattner     {
135*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
136*30fdc8d8SChris Lattner         err.LogThreaded ("can't open file '%s'", path);
137*30fdc8d8SChris Lattner         return rnb_not_connected;
138*30fdc8d8SChris Lattner     }
139*30fdc8d8SChris Lattner     else
140*30fdc8d8SChris Lattner     {
141*30fdc8d8SChris Lattner         struct termios stdin_termios;
142*30fdc8d8SChris Lattner 
143*30fdc8d8SChris Lattner         if (::tcgetattr (m_conn_port, &stdin_termios) == 0)
144*30fdc8d8SChris Lattner         {
145*30fdc8d8SChris Lattner             stdin_termios.c_lflag &= ~ECHO;     // Turn off echoing
146*30fdc8d8SChris Lattner             stdin_termios.c_lflag &= ~ICANON;   // Get one char at a time
147*30fdc8d8SChris Lattner             ::tcsetattr (m_conn_port, TCSANOW, &stdin_termios);
148*30fdc8d8SChris Lattner         }
149*30fdc8d8SChris Lattner     }
150*30fdc8d8SChris Lattner     return rnb_success;
151*30fdc8d8SChris Lattner }
152*30fdc8d8SChris Lattner 
153*30fdc8d8SChris Lattner int
154*30fdc8d8SChris Lattner RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value)
155*30fdc8d8SChris Lattner {
156*30fdc8d8SChris Lattner     return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value));
157*30fdc8d8SChris Lattner }
158*30fdc8d8SChris Lattner 
159*30fdc8d8SChris Lattner rnb_err_t
160*30fdc8d8SChris Lattner RNBSocket::Disconnect (bool save_errno)
161*30fdc8d8SChris Lattner {
162*30fdc8d8SChris Lattner     if (m_conn_port_from_lockdown)
163*30fdc8d8SChris Lattner         m_conn_port_from_lockdown = false;
164*30fdc8d8SChris Lattner     return ClosePort (m_conn_port, save_errno);
165*30fdc8d8SChris Lattner }
166*30fdc8d8SChris Lattner 
167*30fdc8d8SChris Lattner 
168*30fdc8d8SChris Lattner rnb_err_t
169*30fdc8d8SChris Lattner RNBSocket::Read (std::string &p)
170*30fdc8d8SChris Lattner {
171*30fdc8d8SChris Lattner     char buf[1024];
172*30fdc8d8SChris Lattner     p.clear();
173*30fdc8d8SChris Lattner 
174*30fdc8d8SChris Lattner     // Note that BUF is on the stack so we must be careful to keep any
175*30fdc8d8SChris Lattner     // writes to BUF from overflowing or we'll have security issues.
176*30fdc8d8SChris Lattner 
177*30fdc8d8SChris Lattner     if (m_conn_port == -1)
178*30fdc8d8SChris Lattner         return rnb_err;
179*30fdc8d8SChris Lattner 
180*30fdc8d8SChris Lattner     //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
181*30fdc8d8SChris Lattner     DNBError err;
182*30fdc8d8SChris Lattner     int bytesread = read (m_conn_port, buf, sizeof (buf));
183*30fdc8d8SChris Lattner     if (bytesread <= 0)
184*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
185*30fdc8d8SChris Lattner     else
186*30fdc8d8SChris Lattner         p.append(buf, bytesread);
187*30fdc8d8SChris Lattner 
188*30fdc8d8SChris Lattner     if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
189*30fdc8d8SChris Lattner         err.LogThreaded("::read ( %i, %p, %zu ) => %i", m_conn_port, buf, sizeof (buf), bytesread);
190*30fdc8d8SChris Lattner 
191*30fdc8d8SChris Lattner     // Our port went away - we have to mark this so IsConnected will return the truth.
192*30fdc8d8SChris Lattner     if (bytesread == 0)
193*30fdc8d8SChris Lattner     {
194*30fdc8d8SChris Lattner         m_conn_port = -1;
195*30fdc8d8SChris Lattner         return rnb_not_connected;
196*30fdc8d8SChris Lattner     }
197*30fdc8d8SChris Lattner     else if (bytesread == -1)
198*30fdc8d8SChris Lattner     {
199*30fdc8d8SChris Lattner         m_conn_port = -1;
200*30fdc8d8SChris Lattner         return rnb_err;
201*30fdc8d8SChris Lattner     }
202*30fdc8d8SChris Lattner     // Strip spaces from the end of the buffer
203*30fdc8d8SChris Lattner     while (!p.empty() && isspace (p[p.size() - 1]))
204*30fdc8d8SChris Lattner         p.erase (p.size () - 1);
205*30fdc8d8SChris Lattner 
206*30fdc8d8SChris Lattner     // Most data in the debugserver packets valid printable characters...
207*30fdc8d8SChris Lattner     DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str());
208*30fdc8d8SChris Lattner     return rnb_success;
209*30fdc8d8SChris Lattner }
210*30fdc8d8SChris Lattner 
211*30fdc8d8SChris Lattner rnb_err_t
212*30fdc8d8SChris Lattner RNBSocket::Write (const void *buffer, size_t length)
213*30fdc8d8SChris Lattner {
214*30fdc8d8SChris Lattner     if (m_conn_port == -1)
215*30fdc8d8SChris Lattner         return rnb_err;
216*30fdc8d8SChris Lattner 
217*30fdc8d8SChris Lattner     DNBError err;
218*30fdc8d8SChris Lattner     int bytessent = send (m_conn_port, buffer, length, 0);
219*30fdc8d8SChris Lattner     if (bytessent < 0)
220*30fdc8d8SChris Lattner         err.SetError(errno, DNBError::POSIX);
221*30fdc8d8SChris Lattner 
222*30fdc8d8SChris Lattner     if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
223*30fdc8d8SChris Lattner         err.LogThreaded("::send ( socket = %i, buffer = %p, length = %zu, flags = 0 ) => %i", m_conn_port, buffer, length, bytessent);
224*30fdc8d8SChris Lattner 
225*30fdc8d8SChris Lattner     if (bytessent < 0)
226*30fdc8d8SChris Lattner         return rnb_err;
227*30fdc8d8SChris Lattner 
228*30fdc8d8SChris Lattner     if (bytessent != length)
229*30fdc8d8SChris Lattner         return rnb_err;
230*30fdc8d8SChris Lattner 
231*30fdc8d8SChris Lattner     DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", length, (char *)buffer);   // All data is string based in debugserver, so this is safe
232*30fdc8d8SChris Lattner     DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", length, (char *)buffer);
233*30fdc8d8SChris Lattner 
234*30fdc8d8SChris Lattner     return rnb_success;
235*30fdc8d8SChris Lattner }
236*30fdc8d8SChris Lattner 
237*30fdc8d8SChris Lattner 
238*30fdc8d8SChris Lattner rnb_err_t
239*30fdc8d8SChris Lattner RNBSocket::ClosePort (int& fd, bool save_errno)
240*30fdc8d8SChris Lattner {
241*30fdc8d8SChris Lattner     int close_err = 0;
242*30fdc8d8SChris Lattner     if (fd > 0)
243*30fdc8d8SChris Lattner     {
244*30fdc8d8SChris Lattner         errno = 0;
245*30fdc8d8SChris Lattner         close_err = close (fd);
246*30fdc8d8SChris Lattner         fd = -1;
247*30fdc8d8SChris Lattner     }
248*30fdc8d8SChris Lattner     return close_err != 0 ? rnb_err : rnb_success;
249*30fdc8d8SChris Lattner }
250*30fdc8d8SChris Lattner 
251*30fdc8d8SChris Lattner 
252