blob: 1790ee7f808f48590af4a37ca806f5d3f04b774c [file] [log] [blame]
Greg Clayton363be3f2011-07-15 03:27:12 +00001//===-- CommunicationKDP.cpp ------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11#include "CommunicationKDP.h"
12
13// C Includes
14#include <limits.h>
15#include <string.h>
16
17// C++ Includes
18// Other libraries and framework includes
Greg Clayton1e5b0212011-07-15 16:31:38 +000019#include "lldb/Core/DataExtractor.h"
Greg Clayton363be3f2011-07-15 03:27:12 +000020#include "lldb/Core/Log.h"
21#include "lldb/Core/StreamString.h"
22#include "lldb/Host/FileSpec.h"
23#include "lldb/Host/Host.h"
24#include "lldb/Host/TimeValue.h"
25#include "lldb/Target/Process.h"
26#include "Utility/StringExtractor.h"
27
28// Project includes
29#include "ProcessKDPLog.h"
30
31#define DEBUGSERVER_BASENAME "debugserver"
32
33using namespace lldb;
34using namespace lldb_private;
35
36//----------------------------------------------------------------------
37// CommunicationKDP constructor
38//----------------------------------------------------------------------
39CommunicationKDP::CommunicationKDP (const char *comm_name) :
40 Communication(comm_name),
41 m_packet_timeout (1),
42 m_sequence_mutex (Mutex::eMutexTypeRecursive),
43 m_public_is_running (false),
44 m_private_is_running (false),
Greg Clayton1e5b0212011-07-15 16:31:38 +000045 m_session_key (0),
46 m_request_sequence_id (0),
47 m_exception_sequence_id (0)
Greg Clayton363be3f2011-07-15 03:27:12 +000048{
49}
50
51//----------------------------------------------------------------------
52// Destructor
53//----------------------------------------------------------------------
54CommunicationKDP::~CommunicationKDP()
55{
56 if (IsConnected())
57 {
58 Disconnect();
59 }
60}
61
Greg Clayton1e5b0212011-07-15 16:31:38 +000062bool
63CommunicationKDP::SendRequestPacket (const StreamString &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +000064{
65 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton1e5b0212011-07-15 16:31:38 +000066 return SendRequestPacketNoLock (request_packet);
Greg Clayton363be3f2011-07-15 03:27:12 +000067}
68
Greg Clayton1e5b0212011-07-15 16:31:38 +000069void
70CommunicationKDP::MakeRequestPacketHeader (RequestType request_type,
71 StreamString &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +000072{
Greg Clayton1e5b0212011-07-15 16:31:38 +000073 request_packet.Clear();
74 request_packet.PutHex32 (request_type); // Set the request type
75 request_packet.PutHex8 (ePacketTypeRequest); // Set the packet type
76 request_packet.PutHex8 (++m_request_sequence_id); // Sequence number
77 request_packet.PutHex16 (0); // Pad1 and Pad2 bytes
78 request_packet.PutHex32 (m_session_key); // Session key
Greg Clayton363be3f2011-07-15 03:27:12 +000079}
80
Greg Clayton363be3f2011-07-15 03:27:12 +000081
Greg Clayton1e5b0212011-07-15 16:31:38 +000082bool
83CommunicationKDP::SendRequestPacketNoLock (const StreamString &request_packet)
Greg Clayton363be3f2011-07-15 03:27:12 +000084{
85 if (IsConnected())
86 {
Greg Clayton1e5b0212011-07-15 16:31:38 +000087 const char *packet_data = request_packet.GetData();
88 const size_t packet_size = request_packet.GetSize();
Greg Clayton363be3f2011-07-15 03:27:12 +000089
90 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
91 if (log)
Greg Clayton1e5b0212011-07-15 16:31:38 +000092 {
93 StreamString log_strm;
94 DataExtractor data (packet_data,
95 packet_size,
96 request_packet.GetByteOrder(),
97 request_packet.GetAddressByteSize());
98 data.Dump (&log_strm,
99 0,
100 eFormatBytes,
101 1,
102 packet_size,
103 32, // Num bytes per line
104 0, // Base address
105 0,
106 0);
107
108 log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str());
109 }
Greg Clayton363be3f2011-07-15 03:27:12 +0000110 ConnectionStatus status = eConnectionStatusSuccess;
Greg Clayton363be3f2011-07-15 03:27:12 +0000111
Greg Clayton1e5b0212011-07-15 16:31:38 +0000112 size_t bytes_written = Write (packet_data,
113 packet_size,
114 status,
115 NULL);
116
117 if (bytes_written == packet_size)
118 return true;
119
120 if (log)
121 log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size);
122 }
123 return false;
Greg Clayton363be3f2011-07-15 03:27:12 +0000124}
125
126bool
127CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker)
128{
129 return locker.TryLock (m_sequence_mutex.GetMutex());
130}
131
132
133bool
134CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
135{
136 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
137}
138
139size_t
140CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (StringExtractor &packet, uint32_t timeout_usec)
141{
142 Mutex::Locker locker(m_sequence_mutex);
143 return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
144}
145
146size_t
147CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &packet, uint32_t timeout_usec)
148{
149 uint8_t buffer[8192];
150 Error error;
151
152 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE));
153
154 // Check for a packet from our cache first without trying any reading...
155 if (CheckForPacket (NULL, 0, packet))
156 return packet.GetStringRef().size();
157
158 bool timed_out = false;
159 while (IsConnected() && !timed_out)
160 {
161 lldb::ConnectionStatus status;
162 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
163
164 if (log)
165 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu",
166 __PRETTY_FUNCTION__,
167 timeout_usec,
168 Communication::ConnectionStatusAsCString (status),
169 error.AsCString(),
170 bytes_read);
171
172 if (bytes_read > 0)
173 {
174 if (CheckForPacket (buffer, bytes_read, packet))
175 return packet.GetStringRef().size();
176 }
177 else
178 {
179 switch (status)
180 {
181 case eConnectionStatusTimedOut:
182 timed_out = true;
183 break;
184 case eConnectionStatusSuccess:
185 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
186 break;
187
188 case eConnectionStatusEndOfFile:
189 case eConnectionStatusNoConnection:
190 case eConnectionStatusLostConnection:
191 case eConnectionStatusError:
192 Disconnect();
193 break;
194 }
195 }
196 }
197 packet.Clear ();
198 return 0;
199}
200
201bool
202CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractor &packet)
203{
204 // Put the packet data into the buffer in a thread safe fashion
205 Mutex::Locker locker(m_bytes_mutex);
206
207 LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS));
208
209 if (src && src_len > 0)
210 {
211 if (log && log->GetVerbose())
212 {
213 StreamString s;
214 log->Printf ("CommunicationKDP::%s adding %u bytes: %.*s",
215 __FUNCTION__,
216 (uint32_t)src_len,
217 (uint32_t)src_len,
218 src);
219 }
220 m_bytes.append ((const char *)src, src_len);
221 }
222
223 // Parse up the packets into gdb remote packets
224 if (!m_bytes.empty())
225 {
Greg Clayton1e5b0212011-07-15 16:31:38 +0000226 // TODO: Figure out if we have a full packet reply
Greg Clayton363be3f2011-07-15 03:27:12 +0000227 }
228 packet.Clear();
229 return false;
230}
231
Greg Clayton1e5b0212011-07-15 16:31:38 +0000232
233CommunicationKDP::ErrorType
234CommunicationKDP::Connect (uint16_t reply_port,
235 uint16_t exc_port,
236 const char *greeting)
237{
238 StreamString request_packet (Stream::eBinary, 4, eByteOrderLittle);
239 MakeRequestPacketHeader (eRequestTypeConnect, request_packet);
240 request_packet.PutHex16(reply_port);
241 request_packet.PutHex16(exc_port);
242 request_packet.PutCString(greeting);
243
244 return eErrorUnimplemented;
245}
246
247CommunicationKDP::ErrorType
248CommunicationKDP::Disconnect ()
249{
250 return eErrorUnimplemented;
251}
252