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 <string.h>
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 //----------------------------------------------------------------------
26 // Constructor
27 //----------------------------------------------------------------------
28 Communication::Communication(const char *name) :
29     Broadcaster (name),
30     m_connection_sp (),
31     m_read_thread (LLDB_INVALID_HOST_THREAD),
32     m_read_thread_enabled (false),
33     m_bytes(),
34     m_bytes_mutex (Mutex::eMutexTypeRecursive),
35     m_write_mutex (Mutex::eMutexTypeNormal),
36     m_callback (NULL),
37     m_callback_baton (NULL),
38     m_close_on_eof (true)
39 
40 {
41     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
42                                  "%p Communication::Communication (name = %s)",
43                                  this, name);
44 }
45 
46 //----------------------------------------------------------------------
47 // Destructor
48 //----------------------------------------------------------------------
49 Communication::~Communication()
50 {
51     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
52                                  "%p Communication::~Communication (name = %s)",
53                                  this, m_broadcaster_name.AsCString(""));
54     Clear();
55 }
56 
57 void
58 Communication::Clear()
59 {
60     StopReadThread (NULL);
61     Disconnect (NULL);
62 }
63 
64 ConnectionStatus
65 Communication::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
66 {
67     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
68 
69     lldb::ConnectionSP connection_sp (m_connection_sp);
70     if (connection_sp.get())
71         return connection_sp->BytesAvailable (timeout_usec, error_ptr);
72     if (error_ptr)
73         error_ptr->SetErrorString("Invalid connection.");
74     return eConnectionStatusNoConnection;
75 }
76 
77 ConnectionStatus
78 Communication::Connect (const char *url, Error *error_ptr)
79 {
80     Clear();
81 
82     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
83 
84     lldb::ConnectionSP connection_sp (m_connection_sp);
85     if (connection_sp.get())
86         return connection_sp->Connect (url, error_ptr);
87     if (error_ptr)
88         error_ptr->SetErrorString("Invalid connection.");
89     return eConnectionStatusNoConnection;
90 }
91 
92 ConnectionStatus
93 Communication::Disconnect (Error *error_ptr)
94 {
95     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
96 
97     lldb::ConnectionSP connection_sp (m_connection_sp);
98     if (connection_sp.get())
99     {
100         ConnectionStatus status = connection_sp->Disconnect (error_ptr);
101         // We currently don't protect connection_sp with any mutex for
102         // multi-threaded environments. So lets not nuke our connection class
103         // without putting some multi-threaded protections in. We also probably
104         // don't want to pay for the overhead it might cause if every time we
105         // access the connection we have to take a lock.
106         //
107         // This auto_ptr will cleanup after itself when this object goes away,
108         // so there is no need to currently have it destroy itself immediately
109         // upon disconnnect.
110         //connection_sp.reset();
111         return status;
112     }
113     return eConnectionStatusNoConnection;
114 }
115 
116 bool
117 Communication::IsConnected () const
118 {
119     lldb::ConnectionSP connection_sp (m_connection_sp);
120     if (connection_sp.get())
121         return connection_sp->IsConnected ();
122     return false;
123 }
124 
125 bool
126 Communication::HasConnection () const
127 {
128     return m_connection_sp.get() != NULL;
129 }
130 
131 size_t
132 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
133 {
134     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
135                                          "%p Communication::Read (dst = %p, dst_len = %zu, timeout_usec = %u) connection = %p",
136                                          this,
137                                          dst,
138                                          dst_len,
139                                          timeout_usec,
140                                          m_connection_sp.get());
141 
142     if (m_read_thread_enabled)
143     {
144         // We have a dedicated read thread that is getting data for us
145         size_t cached_bytes = GetCachedBytes (dst, dst_len);
146         if (cached_bytes > 0 || timeout_usec == 0)
147         {
148             status = eConnectionStatusSuccess;
149             return cached_bytes;
150         }
151 
152         if (m_connection_sp.get() == NULL)
153         {
154             if (error_ptr)
155                 error_ptr->SetErrorString("Invalid connection.");
156             status = eConnectionStatusNoConnection;
157             return 0;
158         }
159         // Set the timeout appropriately
160         TimeValue timeout_time;
161         if (timeout_usec != UINT32_MAX)
162         {
163             timeout_time = TimeValue::Now();
164             timeout_time.OffsetWithMicroSeconds (timeout_usec);
165         }
166 
167         Listener listener ("Communication::Read");
168         listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
169         EventSP event_sp;
170         while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
171         {
172             const uint32_t event_type = event_sp->GetType();
173             if (event_type & eBroadcastBitReadThreadGotBytes)
174             {
175                 return GetCachedBytes (dst, dst_len);
176             }
177 
178             if (event_type & eBroadcastBitReadThreadDidExit)
179             {
180                 Disconnect (NULL);
181                 break;
182             }
183         }
184         return 0;
185     }
186 
187     // We aren't using a read thread, just read the data synchronously in this
188     // thread.
189     lldb::ConnectionSP connection_sp (m_connection_sp);
190     if (connection_sp.get())
191     {
192         status = connection_sp->BytesAvailable (timeout_usec, error_ptr);
193         if (status == eConnectionStatusSuccess)
194             return connection_sp->Read (dst, dst_len, status, error_ptr);
195     }
196 
197     if (error_ptr)
198         error_ptr->SetErrorString("Invalid connection.");
199     status = eConnectionStatusNoConnection;
200     return 0;
201 }
202 
203 
204 size_t
205 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
206 {
207     lldb::ConnectionSP connection_sp (m_connection_sp);
208 
209     Mutex::Locker (m_write_mutex);
210     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
211                                          "%p Communication::Write (src = %p, src_len = %zu) connection = %p",
212                                          this,
213                                          src,
214                                          src_len,
215                                          connection_sp.get());
216 
217     if (connection_sp.get())
218         return connection_sp->Write (src, src_len, status, error_ptr);
219 
220     if (error_ptr)
221         error_ptr->SetErrorString("Invalid connection.");
222     status = eConnectionStatusNoConnection;
223     return 0;
224 }
225 
226 
227 bool
228 Communication::StartReadThread (Error *error_ptr)
229 {
230     if (m_read_thread != LLDB_INVALID_HOST_THREAD)
231         return true;
232 
233     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
234                                  "%p Communication::StartReadThread ()", this);
235 
236 
237     char thread_name[1024];
238     snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
239 
240     m_read_thread_enabled = true;
241     m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
242     if (m_read_thread == LLDB_INVALID_HOST_THREAD)
243         m_read_thread_enabled = false;
244     return m_read_thread_enabled;
245 }
246 
247 bool
248 Communication::StopReadThread (Error *error_ptr)
249 {
250     if (m_read_thread == LLDB_INVALID_HOST_THREAD)
251         return true;
252 
253     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
254                                  "%p Communication::StopReadThread ()", this);
255 
256     m_read_thread_enabled = false;
257 
258     BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
259 
260     Host::ThreadCancel (m_read_thread, error_ptr);
261 
262     bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
263     m_read_thread = LLDB_INVALID_HOST_THREAD;
264     return status;
265 }
266 
267 
268 size_t
269 Communication::GetCachedBytes (void *dst, size_t dst_len)
270 {
271     Mutex::Locker locker(m_bytes_mutex);
272     if (m_bytes.size() > 0)
273     {
274         // If DST is NULL and we have a thread, then return the number
275         // of bytes that are available so the caller can call again
276         if (dst == NULL)
277             return m_bytes.size();
278 
279         const size_t len = std::min<size_t>(dst_len, m_bytes.size());
280 
281         ::memcpy (dst, m_bytes.c_str(), len);
282         m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
283 
284         return len;
285     }
286     return 0;
287 }
288 
289 void
290 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
291 {
292     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
293                                  "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
294                                  this, bytes, len, broadcast);
295     if (bytes == NULL || len == 0)
296         return;
297     if (m_callback)
298     {
299         // If the user registered a callback, then call it and do not broadcast
300         m_callback (m_callback_baton, bytes, len);
301     }
302     else
303     {
304         Mutex::Locker locker(m_bytes_mutex);
305         m_bytes.append ((const char *)bytes, len);
306         if (broadcast)
307             BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
308     }
309 }
310 
311 size_t
312 Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
313 {
314     lldb::ConnectionSP connection_sp (m_connection_sp);
315     if (connection_sp.get())
316         return connection_sp->Read (dst, dst_len, status, error_ptr);
317     return 0;
318 }
319 
320 bool
321 Communication::ReadThreadIsRunning ()
322 {
323     return m_read_thread_enabled;
324 }
325 
326 void *
327 Communication::ReadThread (void *p)
328 {
329     Communication *comm = (Communication *)p;
330 
331     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
332 
333     if (log)
334         log->Printf ("%p Communication::ReadThread () thread starting...", p);
335 
336     uint8_t buf[1024];
337 
338     Error error;
339     ConnectionStatus status = eConnectionStatusSuccess;
340     bool done = false;
341     while (!done && comm->m_read_thread_enabled)
342     {
343         status = comm->BytesAvailable (UINT32_MAX, &error);
344 
345         if (status == eConnectionStatusSuccess)
346         {
347             size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), status, &error);
348             if (bytes_read > 0)
349                 comm->AppendBytesToCache (buf, bytes_read, true, status);
350         }
351 
352         switch (status)
353         {
354         case eConnectionStatusSuccess:
355             break;
356 
357         case eConnectionStatusEndOfFile:
358         case eConnectionStatusNoConnection:     // No connection
359         case eConnectionStatusLostConnection:   // Lost connection while connected to a valid connection
360             done = true;
361             // Fall through...
362         default:
363         case eConnectionStatusError:            // Check GetError() for details
364         case eConnectionStatusTimedOut:         // Request timed out
365             if (log)
366                 error.LogIfError(log.get(), "%p Communication::BytesAvailable () => status = %i", p, status);
367             break;
368         }
369     }
370     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
371     if (log)
372         log->Printf ("%p Communication::ReadThread () thread exiting...", p);
373 
374     // Let clients know that this thread is exiting
375     comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
376     comm->m_read_thread_enabled = false;
377     comm->Disconnect();
378     return NULL;
379 }
380 
381 void
382 Communication::SetReadThreadBytesReceivedCallback
383 (
384     ReadThreadBytesReceived callback,
385     void *callback_baton
386 )
387 {
388     m_callback = callback;
389     m_callback_baton = callback_baton;
390 }
391 
392 void
393 Communication::SetConnection (Connection *connection)
394 {
395     StopReadThread(NULL);
396     Disconnect (NULL);
397     m_connection_sp.reset(connection);
398 }
399 
400 const char *
401 Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
402 {
403     switch (status)
404     {
405     case eConnectionStatusSuccess:        return "success";
406     case eConnectionStatusError:          return "error";
407     case eConnectionStatusTimedOut:       return "timed out";
408     case eConnectionStatusNoConnection:   return "no connection";
409     case eConnectionStatusLostConnection: return "lost connection";
410     }
411 
412     static char unknown_state_string[64];
413     snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
414     return unknown_state_string;
415 }
416