1 //===-- 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"
20 #include "lldb/Host/Host.h"
21 #include <string.h>
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 //----------------------------------------------------------------------
27 // Constructor
28 //----------------------------------------------------------------------
29 Communication::Communication(const char *name) :
30     Broadcaster (name),
31     m_connection_sp (),
32     m_read_thread (LLDB_INVALID_HOST_THREAD),
33     m_read_thread_enabled (false),
34     m_bytes(),
35     m_bytes_mutex (Mutex::eMutexTypeRecursive),
36     m_write_mutex (Mutex::eMutexTypeNormal),
37     m_callback (NULL),
38     m_callback_baton (NULL),
39     m_close_on_eof (true)
40 
41 {
42     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
43                                  "%p Communication::Communication (name = %s)",
44                                  this, name);
45 
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");
51 }
52 
53 //----------------------------------------------------------------------
54 // Destructor
55 //----------------------------------------------------------------------
56 Communication::~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 
64 void
65 Communication::Clear()
66 {
67     StopReadThread (NULL);
68     Disconnect (NULL);
69 }
70 
71 ConnectionStatus
72 Communication::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 
76     lldb::ConnectionSP connection_sp (m_connection_sp);
77     if (connection_sp.get())
78         return connection_sp->BytesAvailable (timeout_usec, error_ptr);
79     if (error_ptr)
80         error_ptr->SetErrorString("Invalid connection.");
81     return eConnectionStatusNoConnection;
82 }
83 
84 ConnectionStatus
85 Communication::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 
91     lldb::ConnectionSP connection_sp (m_connection_sp);
92     if (connection_sp.get())
93         return connection_sp->Connect (url, error_ptr);
94     if (error_ptr)
95         error_ptr->SetErrorString("Invalid connection.");
96     return eConnectionStatusNoConnection;
97 }
98 
99 ConnectionStatus
100 Communication::Disconnect (Error *error_ptr)
101 {
102     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
103 
104     lldb::ConnectionSP connection_sp (m_connection_sp);
105     if (connection_sp.get())
106     {
107         ConnectionStatus status = connection_sp->Disconnect (error_ptr);
108         // We currently don't protect connection_sp with any mutex for
109         // 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.
117         //connection_sp.reset();
118         return status;
119     }
120     return eConnectionStatusNoConnection;
121 }
122 
123 bool
124 Communication::IsConnected () const
125 {
126     lldb::ConnectionSP connection_sp (m_connection_sp);
127     if (connection_sp.get())
128         return connection_sp->IsConnected ();
129     return false;
130 }
131 
132 bool
133 Communication::HasConnection () const
134 {
135     return m_connection_sp.get() != NULL;
136 }
137 
138 size_t
139 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
140 {
141     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
142                                          "%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());
148 
149     if (m_read_thread_enabled)
150     {
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 
159         if (m_connection_sp.get() == NULL)
160         {
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.
196     lldb::ConnectionSP connection_sp (m_connection_sp);
197     if (connection_sp.get())
198     {
199         status = connection_sp->BytesAvailable (timeout_usec, error_ptr);
200         if (status == eConnectionStatusSuccess)
201             return connection_sp->Read (dst, dst_len, status, error_ptr);
202     }
203 
204     if (error_ptr)
205         error_ptr->SetErrorString("Invalid connection.");
206     status = eConnectionStatusNoConnection;
207     return 0;
208 }
209 
210 
211 size_t
212 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
213 {
214     lldb::ConnectionSP connection_sp (m_connection_sp);
215 
216     Mutex::Locker (m_write_mutex);
217     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);
226 
227     if (error_ptr)
228         error_ptr->SetErrorString("Invalid connection.");
229     status = eConnectionStatusNoConnection;
230     return 0;
231 }
232 
233 
234 bool
235 Communication::StartReadThread (Error *error_ptr)
236 {
237     if (error_ptr)
238         error_ptr->Clear();
239 
240     if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
241         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 
250     m_read_thread_enabled = true;
251     m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
252     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
253         m_read_thread_enabled = false;
254     return m_read_thread_enabled;
255 }
256 
257 bool
258 Communication::StopReadThread (Error *error_ptr)
259 {
260     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
261         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 
272     bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
273     m_read_thread = LLDB_INVALID_HOST_THREAD;
274     return status;
275 }
276 
277 
278 size_t
279 Communication::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 
291         ::memcpy (dst, m_bytes.c_str(), len);
292         m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
293 
294         return len;
295     }
296     return 0;
297 }
298 
299 void
300 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
301 {
302     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
303                                  "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
304                                  this, bytes, len, broadcast);
305     if ((bytes == NULL || len == 0)
306         && (status != lldb::eConnectionStatusEndOfFile))
307         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 
322 size_t
323 Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
324 {
325     lldb::ConnectionSP connection_sp (m_connection_sp);
326     if (connection_sp.get())
327         return connection_sp->Read (dst, dst_len, status, error_ptr);
328     return 0;
329 }
330 
331 bool
332 Communication::ReadThreadIsRunning ()
333 {
334     return m_read_thread_enabled;
335 }
336 
337 void *
338 Communication::ReadThread (void *p)
339 {
340     Communication *comm = (Communication *)p;
341 
342     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
343 
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)
360                 comm->AppendBytesToCache (buf, bytes_read, true, status);
361             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             }
368         }
369 
370         switch (status)
371         {
372         case eConnectionStatusSuccess:
373             break;
374 
375         case eConnectionStatusEndOfFile:
376             if (comm->GetCloseOnEOF())
377                  done = true;
378              break;
379         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
386             if (log)
387                 error.LogIfError(log.get(), "%p Communication::BytesAvailable () => status = %i", p, status);
388             break;
389         }
390     }
391     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
392     if (log)
393         log->Printf ("%p Communication::ReadThread () thread exiting...", p);
394 
395     // Let clients know that this thread is exiting
396     comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
397     comm->m_read_thread_enabled = false;
398     comm->Disconnect();
399     return NULL;
400 }
401 
402 void
403 Communication::SetReadThreadBytesReceivedCallback
404 (
405     ReadThreadBytesReceived callback,
406     void *callback_baton
407 )
408 {
409     m_callback = callback;
410     m_callback_baton = callback_baton;
411 }
412 
413 void
414 Communication::SetConnection (Connection *connection)
415 {
416     StopReadThread(NULL);
417     Disconnect (NULL);
418     m_connection_sp.reset(connection);
419 }
420 
421 const char *
422 Communication::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";
431     case eConnectionStatusEndOfFile:      return "end of file";
432     }
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 }
438