blob: 45850f3858b621ce62f26779f8e5313503e849c5 [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{
Greg Clayton756f8ae2011-08-19 23:28:37 +000067 SetReadThreadBytesReceivedCallback (NULL, NULL);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068 Disconnect (NULL);
Greg Clayton74d41932012-01-31 04:56:17 +000069 StopReadThread (NULL);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070}
71
72ConnectionStatus
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073Communication::Connect (const char *url, Error *error_ptr)
74{
75 Clear();
76
77 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
78
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000079 lldb::ConnectionSP connection_sp (m_connection_sp);
80 if (connection_sp.get())
81 return connection_sp->Connect (url, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082 if (error_ptr)
83 error_ptr->SetErrorString("Invalid connection.");
84 return eConnectionStatusNoConnection;
85}
86
87ConnectionStatus
88Communication::Disconnect (Error *error_ptr)
89{
90 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
91
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000092 lldb::ConnectionSP connection_sp (m_connection_sp);
93 if (connection_sp.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 {
Greg Clayton8b2fe6d2010-12-14 02:59:59 +000095 ConnectionStatus status = connection_sp->Disconnect (error_ptr);
96 // We currently don't protect connection_sp with any mutex for
Greg Claytonbfae66a2010-12-12 21:50:57 +000097 // multi-threaded environments. So lets not nuke our connection class
98 // without putting some multi-threaded protections in. We also probably
99 // don't want to pay for the overhead it might cause if every time we
100 // access the connection we have to take a lock.
101 //
102 // This auto_ptr will cleanup after itself when this object goes away,
103 // so there is no need to currently have it destroy itself immediately
104 // upon disconnnect.
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000105 //connection_sp.reset();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 return status;
107 }
108 return eConnectionStatusNoConnection;
109}
110
111bool
112Communication::IsConnected () const
113{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000114 lldb::ConnectionSP connection_sp (m_connection_sp);
115 if (connection_sp.get())
116 return connection_sp->IsConnected ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 return false;
118}
119
120bool
121Communication::HasConnection () const
122{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000123 return m_connection_sp.get() != NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000124}
125
126size_t
127Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
128{
129 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
Greg Clayton73bf5db2011-06-17 01:22:15 +0000130 "%p Communication::Read (dst = %p, dst_len = %zu, timeout = %u usec) connection = %p",
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000131 this,
132 dst,
133 dst_len,
134 timeout_usec,
135 m_connection_sp.get());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000137 if (m_read_thread_enabled)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 {
139 // We have a dedicated read thread that is getting data for us
140 size_t cached_bytes = GetCachedBytes (dst, dst_len);
141 if (cached_bytes > 0 || timeout_usec == 0)
142 {
143 status = eConnectionStatusSuccess;
144 return cached_bytes;
145 }
146
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000147 if (m_connection_sp.get() == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148 {
149 if (error_ptr)
150 error_ptr->SetErrorString("Invalid connection.");
151 status = eConnectionStatusNoConnection;
152 return 0;
153 }
154 // Set the timeout appropriately
155 TimeValue timeout_time;
156 if (timeout_usec != UINT32_MAX)
157 {
158 timeout_time = TimeValue::Now();
159 timeout_time.OffsetWithMicroSeconds (timeout_usec);
160 }
161
162 Listener listener ("Communication::Read");
163 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
164 EventSP event_sp;
165 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
166 {
167 const uint32_t event_type = event_sp->GetType();
168 if (event_type & eBroadcastBitReadThreadGotBytes)
169 {
170 return GetCachedBytes (dst, dst_len);
171 }
172
173 if (event_type & eBroadcastBitReadThreadDidExit)
174 {
175 Disconnect (NULL);
176 break;
177 }
178 }
179 return 0;
180 }
181
182 // We aren't using a read thread, just read the data synchronously in this
183 // thread.
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000184 lldb::ConnectionSP connection_sp (m_connection_sp);
185 if (connection_sp.get())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186 {
Greg Clayton73bf5db2011-06-17 01:22:15 +0000187 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188 }
189
190 if (error_ptr)
191 error_ptr->SetErrorString("Invalid connection.");
192 status = eConnectionStatusNoConnection;
193 return 0;
194}
195
196
197size_t
198Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
199{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000200 lldb::ConnectionSP connection_sp (m_connection_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201
Greg Clayton7ec3d402011-01-27 09:02:32 +0000202 Mutex::Locker (m_write_mutex);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000203 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
204 "%p Communication::Write (src = %p, src_len = %zu) connection = %p",
205 this,
206 src,
207 src_len,
208 connection_sp.get());
209
210 if (connection_sp.get())
211 return connection_sp->Write (src, src_len, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000212
213 if (error_ptr)
214 error_ptr->SetErrorString("Invalid connection.");
215 status = eConnectionStatusNoConnection;
216 return 0;
217}
218
219
220bool
221Communication::StartReadThread (Error *error_ptr)
222{
Greg Clayton1cb64962011-03-24 04:28:38 +0000223 if (error_ptr)
224 error_ptr->Clear();
225
Greg Clayton2da6d492011-02-08 01:34:25 +0000226 if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227 return true;
228
229 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
230 "%p Communication::StartReadThread ()", this);
231
232
233 char thread_name[1024];
234 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
235
Greg Clayton86c3f342010-09-15 05:19:45 +0000236 m_read_thread_enabled = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237 m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
Greg Clayton2da6d492011-02-08 01:34:25 +0000238 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Greg Clayton86c3f342010-09-15 05:19:45 +0000239 m_read_thread_enabled = false;
Greg Clayton26661bc2010-07-23 15:43:25 +0000240 return m_read_thread_enabled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241}
242
243bool
244Communication::StopReadThread (Error *error_ptr)
245{
Greg Clayton2da6d492011-02-08 01:34:25 +0000246 if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000247 return true;
248
249 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
250 "%p Communication::StopReadThread ()", this);
251
252 m_read_thread_enabled = false;
253
254 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
255
Greg Clayton74d41932012-01-31 04:56:17 +0000256 //Host::ThreadCancel (m_read_thread, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000258 bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
Greg Clayton26661bc2010-07-23 15:43:25 +0000259 m_read_thread = LLDB_INVALID_HOST_THREAD;
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000260 return status;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261}
262
263
264size_t
265Communication::GetCachedBytes (void *dst, size_t dst_len)
266{
267 Mutex::Locker locker(m_bytes_mutex);
268 if (m_bytes.size() > 0)
269 {
270 // If DST is NULL and we have a thread, then return the number
271 // of bytes that are available so the caller can call again
272 if (dst == NULL)
273 return m_bytes.size();
274
275 const size_t len = std::min<size_t>(dst_len, m_bytes.size());
276
Greg Clayton471b31c2010-07-20 22:52:08 +0000277 ::memcpy (dst, m_bytes.c_str(), len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
279
280 return len;
281 }
282 return 0;
283}
284
285void
Caroline Ticeefed6132010-11-19 20:47:54 +0000286Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000287{
288 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
289 "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
290 this, bytes, len, broadcast);
Caroline Tice9fd58502011-02-03 20:02:43 +0000291 if ((bytes == NULL || len == 0)
292 && (status != lldb::eConnectionStatusEndOfFile))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293 return;
294 if (m_callback)
295 {
296 // If the user registered a callback, then call it and do not broadcast
297 m_callback (m_callback_baton, bytes, len);
298 }
Greg Clayton756f8ae2011-08-19 23:28:37 +0000299 else if (bytes != NULL && len > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300 {
301 Mutex::Locker locker(m_bytes_mutex);
302 m_bytes.append ((const char *)bytes, len);
303 if (broadcast)
304 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
305 }
306}
307
308size_t
Greg Clayton73bf5db2011-06-17 01:22:15 +0000309Communication::ReadFromConnection (void *dst,
310 size_t dst_len,
311 uint32_t timeout_usec,
312 ConnectionStatus &status,
313 Error *error_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314{
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000315 lldb::ConnectionSP connection_sp (m_connection_sp);
316 if (connection_sp.get())
Greg Clayton73bf5db2011-06-17 01:22:15 +0000317 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 return 0;
319}
320
Caroline Tice82305fc2010-12-02 18:31:56 +0000321bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322Communication::ReadThreadIsRunning ()
323{
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000324 return m_read_thread_enabled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325}
326
327void *
328Communication::ReadThread (void *p)
329{
330 Communication *comm = (Communication *)p;
331
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000332 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000333
334 if (log)
335 log->Printf ("%p Communication::ReadThread () thread starting...", p);
336
337 uint8_t buf[1024];
338
339 Error error;
340 ConnectionStatus status = eConnectionStatusSuccess;
341 bool done = false;
342 while (!done && comm->m_read_thread_enabled)
343 {
Peter Collingbourneba23ca02011-06-18 23:52:14 +0000344 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
Greg Clayton73bf5db2011-06-17 01:22:15 +0000345 if (bytes_read > 0)
346 comm->AppendBytesToCache (buf, bytes_read, true, status);
347 else if ((bytes_read == 0)
348 && status == eConnectionStatusEndOfFile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000349 {
Greg Clayton73bf5db2011-06-17 01:22:15 +0000350 if (comm->GetCloseOnEOF ())
351 comm->Disconnect ();
352 comm->AppendBytesToCache (buf, bytes_read, true, status);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000353 }
354
355 switch (status)
356 {
357 case eConnectionStatusSuccess:
358 break;
359
Greg Clayton7788e5f2010-12-04 02:22:36 +0000360 case eConnectionStatusEndOfFile:
Caroline Tice9fd58502011-02-03 20:02:43 +0000361 if (comm->GetCloseOnEOF())
362 done = true;
363 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 case eConnectionStatusNoConnection: // No connection
365 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
366 done = true;
367 // Fall through...
368 default:
369 case eConnectionStatusError: // Check GetError() for details
370 case eConnectionStatusTimedOut: // Request timed out
Greg Clayton2d4edfb2010-11-06 01:53:30 +0000371 if (log)
Greg Clayton644247c2011-07-07 01:59:51 +0000372 error.LogIfError(log.get(),
373 "%p Communication::ReadFromConnection () => status = %s",
374 p,
375 Communication::ConnectionStatusAsCString (status));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 break;
377 }
378 }
Caroline Tice20ad3c42010-10-29 21:48:37 +0000379 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 if (log)
381 log->Printf ("%p Communication::ReadThread () thread exiting...", p);
382
383 // Let clients know that this thread is exiting
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
Stephen Wilsona08cfb12011-01-12 04:22:54 +0000385 comm->m_read_thread_enabled = false;
Greg Clayton74d41932012-01-31 04:56:17 +0000386 comm->m_read_thread = LLDB_INVALID_HOST_THREAD;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387 return NULL;
388}
389
390void
391Communication::SetReadThreadBytesReceivedCallback
392(
393 ReadThreadBytesReceived callback,
394 void *callback_baton
395)
396{
397 m_callback = callback;
398 m_callback_baton = callback_baton;
399}
400
401void
402Communication::SetConnection (Connection *connection)
403{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000404 Disconnect (NULL);
Greg Clayton74d41932012-01-31 04:56:17 +0000405 StopReadThread(NULL);
Greg Clayton8b2fe6d2010-12-14 02:59:59 +0000406 m_connection_sp.reset(connection);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000407}
Caroline Ticeceb6b132010-10-26 03:11:13 +0000408
409const char *
410Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
411{
412 switch (status)
413 {
414 case eConnectionStatusSuccess: return "success";
415 case eConnectionStatusError: return "error";
416 case eConnectionStatusTimedOut: return "timed out";
417 case eConnectionStatusNoConnection: return "no connection";
418 case eConnectionStatusLostConnection: return "lost connection";
Greg Clayton7a5388b2011-03-20 04:57:14 +0000419 case eConnectionStatusEndOfFile: return "end of file";
Caroline Ticeceb6b132010-10-26 03:11:13 +0000420 }
421
422 static char unknown_state_string[64];
423 snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
424 return unknown_state_string;
425}