blob: 789228a5b9ae093c2bb1602cb0846bf17b9c830b [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Communication.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// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
14#include "lldb/lldb-private-log.h"
15#include "lldb/Core/Communication.h"
16#include "lldb/Core/Connection.h"
17#include "lldb/Core/Log.h"
18#include "lldb/Core/Timer.h"
19#include "lldb/Core/Event.h"
Greg Clayton7fb56d02011-02-01 01:31:41 +000020#include "lldb/Host/Host.h"
Eli Friedman88966972010-06-09 08:50:27 +000021#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23using namespace lldb;
24using namespace lldb_private;
25
26//----------------------------------------------------------------------
27// Constructor
28//----------------------------------------------------------------------
Greg Claytond46c87a2010-12-04 02:39:47 +000029Communication::Communication(const char *name) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030 Broadcaster (name),
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000031 m_connection_sp (),
Eli Friedman8878f872010-07-09 22:53:18 +000032 m_read_thread (LLDB_INVALID_HOST_THREAD),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033 m_read_thread_enabled (false),
34 m_bytes(),
35 m_bytes_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton7ec3d402011-01-27 09:02:32 +000036 m_write_mutex (Mutex::eMutexTypeNormal),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037 m_callback (NULL),
Caroline Tice82305fc2010-12-02 18:31:56 +000038 m_callback_baton (NULL),
Greg Claytond46c87a2010-12-04 02:39:47 +000039 m_close_on_eof (true)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040
41{
42 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
43 "%p Communication::Communication (name = %s)",
44 this, name);
45}
46
47//----------------------------------------------------------------------
48// Destructor
49//----------------------------------------------------------------------
50Communication::~Communication()
51{
52 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
53 "%p Communication::~Communication (name = %s)",
54 this, m_broadcaster_name.AsCString(""));
55 Clear();
56}
57
58void
59Communication::Clear()
60{
61 StopReadThread (NULL);
62 Disconnect (NULL);
63}
64
65ConnectionStatus
66Communication::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
67{
68 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
69
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000070 lldb::ConnectionSP connection_sp (m_connection_sp);
71 if (connection_sp.get())
72 return connection_sp->BytesAvailable (timeout_usec, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073 if (error_ptr)
74 error_ptr->SetErrorString("Invalid connection.");
75 return eConnectionStatusNoConnection;
76}
77
78ConnectionStatus
79Communication::Connect (const char *url, Error *error_ptr)
80{
81 Clear();
82
83 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
84
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000085 lldb::ConnectionSP connection_sp (m_connection_sp);
86 if (connection_sp.get())
87 return connection_sp->Connect (url, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088 if (error_ptr)
89 error_ptr->SetErrorString("Invalid connection.");
90 return eConnectionStatusNoConnection;
91}
92
93ConnectionStatus
94Communication::Disconnect (Error *error_ptr)
95{
96 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
97
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000098 lldb::ConnectionSP connection_sp (m_connection_sp);
99 if (connection_sp.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 {
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000101 ConnectionStatus status = connection_sp->Disconnect (error_ptr);
102 // We currently don't protect connection_sp with any mutex for
Greg Claytonbfae66a2010-12-12 21:50:57 +0000103 // multi-threaded environments. So lets not nuke our connection class
104 // without putting some multi-threaded protections in. We also probably
105 // don't want to pay for the overhead it might cause if every time we
106 // access the connection we have to take a lock.
107 //
108 // This auto_ptr will cleanup after itself when this object goes away,
109 // so there is no need to currently have it destroy itself immediately
110 // upon disconnnect.
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000111 //connection_sp.reset();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 return status;
113 }
114 return eConnectionStatusNoConnection;
115}
116
117bool
118Communication::IsConnected () const
119{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000120 lldb::ConnectionSP connection_sp (m_connection_sp);
121 if (connection_sp.get())
122 return connection_sp->IsConnected ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123 return false;
124}
125
126bool
127Communication::HasConnection () const
128{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000129 return m_connection_sp.get() != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130}
131
132size_t
133Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
134{
135 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000136 "%p Communication::Read (dst = %p, dst_len = %zu, timeout_usec = %u) connection = %p",
137 this,
138 dst,
139 dst_len,
140 timeout_usec,
141 m_connection_sp.get());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000143 if (m_read_thread_enabled)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144 {
145 // We have a dedicated read thread that is getting data for us
146 size_t cached_bytes = GetCachedBytes (dst, dst_len);
147 if (cached_bytes > 0 || timeout_usec == 0)
148 {
149 status = eConnectionStatusSuccess;
150 return cached_bytes;
151 }
152
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000153 if (m_connection_sp.get() == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154 {
155 if (error_ptr)
156 error_ptr->SetErrorString("Invalid connection.");
157 status = eConnectionStatusNoConnection;
158 return 0;
159 }
160 // Set the timeout appropriately
161 TimeValue timeout_time;
162 if (timeout_usec != UINT32_MAX)
163 {
164 timeout_time = TimeValue::Now();
165 timeout_time.OffsetWithMicroSeconds (timeout_usec);
166 }
167
168 Listener listener ("Communication::Read");
169 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
170 EventSP event_sp;
171 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
172 {
173 const uint32_t event_type = event_sp->GetType();
174 if (event_type & eBroadcastBitReadThreadGotBytes)
175 {
176 return GetCachedBytes (dst, dst_len);
177 }
178
179 if (event_type & eBroadcastBitReadThreadDidExit)
180 {
181 Disconnect (NULL);
182 break;
183 }
184 }
185 return 0;
186 }
187
188 // We aren't using a read thread, just read the data synchronously in this
189 // thread.
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000190 lldb::ConnectionSP connection_sp (m_connection_sp);
191 if (connection_sp.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192 {
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000193 status = connection_sp->BytesAvailable (timeout_usec, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 if (status == eConnectionStatusSuccess)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000195 return connection_sp->Read (dst, dst_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196 }
197
198 if (error_ptr)
199 error_ptr->SetErrorString("Invalid connection.");
200 status = eConnectionStatusNoConnection;
201 return 0;
202}
203
204
205size_t
206Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
207{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000208 lldb::ConnectionSP connection_sp (m_connection_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000209
Greg Clayton7ec3d402011-01-27 09:02:32 +0000210 Mutex::Locker (m_write_mutex);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000211 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
212 "%p Communication::Write (src = %p, src_len = %zu) connection = %p",
213 this,
214 src,
215 src_len,
216 connection_sp.get());
217
218 if (connection_sp.get())
219 return connection_sp->Write (src, src_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220
221 if (error_ptr)
222 error_ptr->SetErrorString("Invalid connection.");
223 status = eConnectionStatusNoConnection;
224 return 0;
225}
226
227
228bool
229Communication::StartReadThread (Error *error_ptr)
230{
Greg Clayton1cb64962011-03-24 04:28:38 +0000231 if (error_ptr)
232 error_ptr->Clear();
233
Greg Clayton2da6d492011-02-08 01:34:25 +0000234 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235 return true;
236
237 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
238 "%p Communication::StartReadThread ()", this);
239
240
241 char thread_name[1024];
242 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
243
Greg Clayton86c3f342010-09-15 05:19:45 +0000244 m_read_thread_enabled = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000245 m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
Greg Clayton2da6d492011-02-08 01:34:25 +0000246 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Greg Clayton86c3f342010-09-15 05:19:45 +0000247 m_read_thread_enabled = false;
Greg Clayton26661bc2010-07-23 15:43:25 +0000248 return m_read_thread_enabled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249}
250
251bool
252Communication::StopReadThread (Error *error_ptr)
253{
Greg Clayton2da6d492011-02-08 01:34:25 +0000254 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255 return true;
256
257 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
258 "%p Communication::StopReadThread ()", this);
259
260 m_read_thread_enabled = false;
261
262 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
263
264 Host::ThreadCancel (m_read_thread, error_ptr);
265
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000266 bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
Greg Clayton26661bc2010-07-23 15:43:25 +0000267 m_read_thread = LLDB_INVALID_HOST_THREAD;
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000268 return status;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269}
270
271
272size_t
273Communication::GetCachedBytes (void *dst, size_t dst_len)
274{
275 Mutex::Locker locker(m_bytes_mutex);
276 if (m_bytes.size() > 0)
277 {
278 // If DST is NULL and we have a thread, then return the number
279 // of bytes that are available so the caller can call again
280 if (dst == NULL)
281 return m_bytes.size();
282
283 const size_t len = std::min<size_t>(dst_len, m_bytes.size());
284
Greg Clayton471b31c2010-07-20 22:52:08 +0000285 ::memcpy (dst, m_bytes.c_str(), len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000286 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
287
288 return len;
289 }
290 return 0;
291}
292
293void
Caroline Ticeefed6132010-11-19 20:47:54 +0000294Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295{
296 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
297 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
298 this, bytes, len, broadcast);
Caroline Tice9fd58502011-02-03 20:02:43 +0000299 if ((bytes == NULL || len == 0)
300 && (status != lldb::eConnectionStatusEndOfFile))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301 return;
302 if (m_callback)
303 {
304 // If the user registered a callback, then call it and do not broadcast
305 m_callback (m_callback_baton, bytes, len);
306 }
307 else
308 {
309 Mutex::Locker locker(m_bytes_mutex);
310 m_bytes.append ((const char *)bytes, len);
311 if (broadcast)
312 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
313 }
314}
315
316size_t
317Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
318{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000319 lldb::ConnectionSP connection_sp (m_connection_sp);
320 if (connection_sp.get())
321 return connection_sp->Read (dst, dst_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322 return 0;
323}
324
Caroline Tice82305fc2010-12-02 18:31:56 +0000325bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326Communication::ReadThreadIsRunning ()
327{
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000328 return m_read_thread_enabled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329}
330
331void *
332Communication::ReadThread (void *p)
333{
334 Communication *comm = (Communication *)p;
335
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000336 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337
338 if (log)
339 log->Printf ("%p Communication::ReadThread () thread starting...", p);
340
341 uint8_t buf[1024];
342
343 Error error;
344 ConnectionStatus status = eConnectionStatusSuccess;
345 bool done = false;
346 while (!done && comm->m_read_thread_enabled)
347 {
348 status = comm->BytesAvailable (UINT32_MAX, &error);
349
350 if (status == eConnectionStatusSuccess)
351 {
352 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error);
353 if (bytes_read > 0)
Caroline Ticeefed6132010-11-19 20:47:54 +0000354 comm->AppendBytesToCache (buf, bytes_read, true, status);
Caroline Tice9fd58502011-02-03 20:02:43 +0000355 else if ((bytes_read == 0)
356 && status == eConnectionStatusEndOfFile)
357 {
358 if (comm->GetCloseOnEOF ())
359 comm->Disconnect ();
360 comm->AppendBytesToCache (buf, bytes_read, true, status);
361 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362 }
363
364 switch (status)
365 {
366 case eConnectionStatusSuccess:
367 break;
368
Greg Clayton7788e5f2010-12-04 02:22:36 +0000369 case eConnectionStatusEndOfFile:
Caroline Tice9fd58502011-02-03 20:02:43 +0000370 if (comm->GetCloseOnEOF())
371 done = true;
372 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 case eConnectionStatusNoConnection: // No connection
374 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
375 done = true;
376 // Fall through...
377 default:
378 case eConnectionStatusError: // Check GetError() for details
379 case eConnectionStatusTimedOut: // Request timed out
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000380 if (log)
381 error.LogIfError(log.get(), "%p Communication::BytesAvailable () => status = %i", p, status);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 break;
383 }
384 }
Caroline Tice20ad3c42010-10-29 21:48:37 +0000385 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000386 if (log)
387 log->Printf ("%p Communication::ReadThread () thread exiting...", p);
388
389 // Let clients know that this thread is exiting
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000391 comm->m_read_thread_enabled = false;
Greg Claytonbfae66a2010-12-12 21:50:57 +0000392 comm->Disconnect();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393 return NULL;
394}
395
396void
397Communication::SetReadThreadBytesReceivedCallback
398(
399 ReadThreadBytesReceived callback,
400 void *callback_baton
401)
402{
403 m_callback = callback;
404 m_callback_baton = callback_baton;
405}
406
407void
408Communication::SetConnection (Connection *connection)
409{
410 StopReadThread(NULL);
411 Disconnect (NULL);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000412 m_connection_sp.reset(connection);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413}
Caroline Ticeceb6b132010-10-26 03:11:13 +0000414
415const char *
416Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
417{
418 switch (status)
419 {
420 case eConnectionStatusSuccess: return "success";
421 case eConnectionStatusError: return "error";
422 case eConnectionStatusTimedOut: return "timed out";
423 case eConnectionStatusNoConnection: return "no connection";
424 case eConnectionStatusLostConnection: return "lost connection";
Greg Clayton7a5388b2011-03-20 04:57:14 +0000425 case eConnectionStatusEndOfFile: return "end of file";
Caroline Ticeceb6b132010-10-26 03:11:13 +0000426 }
427
428 static char unknown_state_string[64];
429 snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
430 return unknown_state_string;
431}