blob: a603d6c7b78d70de49ace6cb529f4085dc08ec94 [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);
Greg Clayton95bf0fd2011-04-01 00:29:43 +000045
46 SetEventName (eBroadcastBitDisconnected, "disconnected");
47 SetEventName (eBroadcastBitReadThreadGotBytes, "got bytes");
48 SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
49 SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
50 SetEventName (eBroadcastBitPacketAvailable, "packet available");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051}
52
53//----------------------------------------------------------------------
54// Destructor
55//----------------------------------------------------------------------
56Communication::~Communication()
57{
58 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
59 "%p Communication::~Communication (name = %s)",
60 this, m_broadcaster_name.AsCString(""));
61 Clear();
62}
63
64void
65Communication::Clear()
66{
67 StopReadThread (NULL);
68 Disconnect (NULL);
69}
70
71ConnectionStatus
72Communication::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
73{
74 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
75
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000076 lldb::ConnectionSP connection_sp (m_connection_sp);
77 if (connection_sp.get())
78 return connection_sp->BytesAvailable (timeout_usec, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 if (error_ptr)
80 error_ptr->SetErrorString("Invalid connection.");
81 return eConnectionStatusNoConnection;
82}
83
84ConnectionStatus
85Communication::Connect (const char *url, Error *error_ptr)
86{
87 Clear();
88
89 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
90
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000091 lldb::ConnectionSP connection_sp (m_connection_sp);
92 if (connection_sp.get())
93 return connection_sp->Connect (url, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 if (error_ptr)
95 error_ptr->SetErrorString("Invalid connection.");
96 return eConnectionStatusNoConnection;
97}
98
99ConnectionStatus
100Communication::Disconnect (Error *error_ptr)
101{
102 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
103
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000104 lldb::ConnectionSP connection_sp (m_connection_sp);
105 if (connection_sp.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 {
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000107 ConnectionStatus status = connection_sp->Disconnect (error_ptr);
108 // We currently don't protect connection_sp with any mutex for
Greg Claytonbfae66a2010-12-12 21:50:57 +0000109 // multi-threaded environments. So lets not nuke our connection class
110 // without putting some multi-threaded protections in. We also probably
111 // don't want to pay for the overhead it might cause if every time we
112 // access the connection we have to take a lock.
113 //
114 // This auto_ptr will cleanup after itself when this object goes away,
115 // so there is no need to currently have it destroy itself immediately
116 // upon disconnnect.
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000117 //connection_sp.reset();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118 return status;
119 }
120 return eConnectionStatusNoConnection;
121}
122
123bool
124Communication::IsConnected () const
125{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000126 lldb::ConnectionSP connection_sp (m_connection_sp);
127 if (connection_sp.get())
128 return connection_sp->IsConnected ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129 return false;
130}
131
132bool
133Communication::HasConnection () const
134{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000135 return m_connection_sp.get() != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136}
137
138size_t
139Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
140{
141 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000142 "%p Communication::Read (dst = %p, dst_len = %zu, timeout_usec = %u) connection = %p",
143 this,
144 dst,
145 dst_len,
146 timeout_usec,
147 m_connection_sp.get());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000149 if (m_read_thread_enabled)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 {
151 // We have a dedicated read thread that is getting data for us
152 size_t cached_bytes = GetCachedBytes (dst, dst_len);
153 if (cached_bytes > 0 || timeout_usec == 0)
154 {
155 status = eConnectionStatusSuccess;
156 return cached_bytes;
157 }
158
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000159 if (m_connection_sp.get() == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 {
161 if (error_ptr)
162 error_ptr->SetErrorString("Invalid connection.");
163 status = eConnectionStatusNoConnection;
164 return 0;
165 }
166 // Set the timeout appropriately
167 TimeValue timeout_time;
168 if (timeout_usec != UINT32_MAX)
169 {
170 timeout_time = TimeValue::Now();
171 timeout_time.OffsetWithMicroSeconds (timeout_usec);
172 }
173
174 Listener listener ("Communication::Read");
175 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
176 EventSP event_sp;
177 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
178 {
179 const uint32_t event_type = event_sp->GetType();
180 if (event_type & eBroadcastBitReadThreadGotBytes)
181 {
182 return GetCachedBytes (dst, dst_len);
183 }
184
185 if (event_type & eBroadcastBitReadThreadDidExit)
186 {
187 Disconnect (NULL);
188 break;
189 }
190 }
191 return 0;
192 }
193
194 // We aren't using a read thread, just read the data synchronously in this
195 // thread.
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000196 lldb::ConnectionSP connection_sp (m_connection_sp);
197 if (connection_sp.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000198 {
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000199 status = connection_sp->BytesAvailable (timeout_usec, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 if (status == eConnectionStatusSuccess)
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000201 return connection_sp->Read (dst, dst_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000202 }
203
204 if (error_ptr)
205 error_ptr->SetErrorString("Invalid connection.");
206 status = eConnectionStatusNoConnection;
207 return 0;
208}
209
210
211size_t
212Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
213{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000214 lldb::ConnectionSP connection_sp (m_connection_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000215
Greg Clayton7ec3d402011-01-27 09:02:32 +0000216 Mutex::Locker (m_write_mutex);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000217 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
218 "%p Communication::Write (src = %p, src_len = %zu) connection = %p",
219 this,
220 src,
221 src_len,
222 connection_sp.get());
223
224 if (connection_sp.get())
225 return connection_sp->Write (src, src_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226
227 if (error_ptr)
228 error_ptr->SetErrorString("Invalid connection.");
229 status = eConnectionStatusNoConnection;
230 return 0;
231}
232
233
234bool
235Communication::StartReadThread (Error *error_ptr)
236{
Greg Clayton1cb64962011-03-24 04:28:38 +0000237 if (error_ptr)
238 error_ptr->Clear();
239
Greg Clayton2da6d492011-02-08 01:34:25 +0000240 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241 return true;
242
243 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
244 "%p Communication::StartReadThread ()", this);
245
246
247 char thread_name[1024];
248 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
249
Greg Clayton86c3f342010-09-15 05:19:45 +0000250 m_read_thread_enabled = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251 m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
Greg Clayton2da6d492011-02-08 01:34:25 +0000252 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Greg Clayton86c3f342010-09-15 05:19:45 +0000253 m_read_thread_enabled = false;
Greg Clayton26661bc2010-07-23 15:43:25 +0000254 return m_read_thread_enabled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255}
256
257bool
258Communication::StopReadThread (Error *error_ptr)
259{
Greg Clayton2da6d492011-02-08 01:34:25 +0000260 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261 return true;
262
263 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
264 "%p Communication::StopReadThread ()", this);
265
266 m_read_thread_enabled = false;
267
268 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
269
270 Host::ThreadCancel (m_read_thread, error_ptr);
271
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000272 bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
Greg Clayton26661bc2010-07-23 15:43:25 +0000273 m_read_thread = LLDB_INVALID_HOST_THREAD;
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000274 return status;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000275}
276
277
278size_t
279Communication::GetCachedBytes (void *dst, size_t dst_len)
280{
281 Mutex::Locker locker(m_bytes_mutex);
282 if (m_bytes.size() > 0)
283 {
284 // If DST is NULL and we have a thread, then return the number
285 // of bytes that are available so the caller can call again
286 if (dst == NULL)
287 return m_bytes.size();
288
289 const size_t len = std::min<size_t>(dst_len, m_bytes.size());
290
Greg Clayton471b31c2010-07-20 22:52:08 +0000291 ::memcpy (dst, m_bytes.c_str(), len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000292 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
293
294 return len;
295 }
296 return 0;
297}
298
299void
Caroline Ticeefed6132010-11-19 20:47:54 +0000300Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301{
302 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
303 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
304 this, bytes, len, broadcast);
Caroline Tice9fd58502011-02-03 20:02:43 +0000305 if ((bytes == NULL || len == 0)
306 && (status != lldb::eConnectionStatusEndOfFile))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307 return;
308 if (m_callback)
309 {
310 // If the user registered a callback, then call it and do not broadcast
311 m_callback (m_callback_baton, bytes, len);
312 }
313 else
314 {
315 Mutex::Locker locker(m_bytes_mutex);
316 m_bytes.append ((const char *)bytes, len);
317 if (broadcast)
318 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
319 }
320}
321
322size_t
323Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
324{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000325 lldb::ConnectionSP connection_sp (m_connection_sp);
326 if (connection_sp.get())
327 return connection_sp->Read (dst, dst_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328 return 0;
329}
330
Caroline Tice82305fc2010-12-02 18:31:56 +0000331bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000332Communication::ReadThreadIsRunning ()
333{
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000334 return m_read_thread_enabled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000335}
336
337void *
338Communication::ReadThread (void *p)
339{
340 Communication *comm = (Communication *)p;
341
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000342 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000343
344 if (log)
345 log->Printf ("%p Communication::ReadThread () thread starting...", p);
346
347 uint8_t buf[1024];
348
349 Error error;
350 ConnectionStatus status = eConnectionStatusSuccess;
351 bool done = false;
352 while (!done && comm->m_read_thread_enabled)
353 {
354 status = comm->BytesAvailable (UINT32_MAX, &error);
355
356 if (status == eConnectionStatusSuccess)
357 {
358 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error);
359 if (bytes_read > 0)
Caroline Ticeefed6132010-11-19 20:47:54 +0000360 comm->AppendBytesToCache (buf, bytes_read, true, status);
Caroline Tice9fd58502011-02-03 20:02:43 +0000361 else if ((bytes_read == 0)
362 && status == eConnectionStatusEndOfFile)
363 {
364 if (comm->GetCloseOnEOF ())
365 comm->Disconnect ();
366 comm->AppendBytesToCache (buf, bytes_read, true, status);
367 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368 }
369
370 switch (status)
371 {
372 case eConnectionStatusSuccess:
373 break;
374
Greg Clayton7788e5f2010-12-04 02:22:36 +0000375 case eConnectionStatusEndOfFile:
Caroline Tice9fd58502011-02-03 20:02:43 +0000376 if (comm->GetCloseOnEOF())
377 done = true;
378 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379 case eConnectionStatusNoConnection: // No connection
380 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
381 done = true;
382 // Fall through...
383 default:
384 case eConnectionStatusError: // Check GetError() for details
385 case eConnectionStatusTimedOut: // Request timed out
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000386 if (log)
387 error.LogIfError(log.get(), "%p Communication::BytesAvailable () => status = %i", p, status);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388 break;
389 }
390 }
Caroline Tice20ad3c42010-10-29 21:48:37 +0000391 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 if (log)
393 log->Printf ("%p Communication::ReadThread () thread exiting...", p);
394
395 // Let clients know that this thread is exiting
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000397 comm->m_read_thread_enabled = false;
Greg Claytonbfae66a2010-12-12 21:50:57 +0000398 comm->Disconnect();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 return NULL;
400}
401
402void
403Communication::SetReadThreadBytesReceivedCallback
404(
405 ReadThreadBytesReceived callback,
406 void *callback_baton
407)
408{
409 m_callback = callback;
410 m_callback_baton = callback_baton;
411}
412
413void
414Communication::SetConnection (Connection *connection)
415{
416 StopReadThread(NULL);
417 Disconnect (NULL);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000418 m_connection_sp.reset(connection);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000419}
Caroline Ticeceb6b132010-10-26 03:11:13 +0000420
421const char *
422Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
423{
424 switch (status)
425 {
426 case eConnectionStatusSuccess: return "success";
427 case eConnectionStatusError: return "error";
428 case eConnectionStatusTimedOut: return "timed out";
429 case eConnectionStatusNoConnection: return "no connection";
430 case eConnectionStatusLostConnection: return "lost connection";
Greg Clayton7a5388b2011-03-20 04:57:14 +0000431 case eConnectionStatusEndOfFile: return "end of file";
Caroline Ticeceb6b132010-10-26 03:11:13 +0000432 }
433
434 static char unknown_state_string[64];
435 snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
436 return unknown_state_string;
437}