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     SetReadThreadBytesReceivedCallback (NULL, NULL);
68     StopReadThread (NULL);
69     Disconnect (NULL);
70 }
71 
72 ConnectionStatus
73 Communication::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 
79     lldb::ConnectionSP connection_sp (m_connection_sp);
80     if (connection_sp.get())
81         return connection_sp->Connect (url, error_ptr);
82     if (error_ptr)
83         error_ptr->SetErrorString("Invalid connection.");
84     return eConnectionStatusNoConnection;
85 }
86 
87 ConnectionStatus
88 Communication::Disconnect (Error *error_ptr)
89 {
90     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
91 
92     lldb::ConnectionSP connection_sp (m_connection_sp);
93     if (connection_sp.get())
94     {
95         ConnectionStatus status = connection_sp->Disconnect (error_ptr);
96         // We currently don't protect connection_sp with any mutex for
97         // 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.
105         //connection_sp.reset();
106         return status;
107     }
108     return eConnectionStatusNoConnection;
109 }
110 
111 bool
112 Communication::IsConnected () const
113 {
114     lldb::ConnectionSP connection_sp (m_connection_sp);
115     if (connection_sp.get())
116         return connection_sp->IsConnected ();
117     return false;
118 }
119 
120 bool
121 Communication::HasConnection () const
122 {
123     return m_connection_sp.get() != NULL;
124 }
125 
126 size_t
127 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
128 {
129     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
130                                          "%p Communication::Read (dst = %p, dst_len = %zu, timeout = %u usec) connection = %p",
131                                          this,
132                                          dst,
133                                          dst_len,
134                                          timeout_usec,
135                                          m_connection_sp.get());
136 
137     if (m_read_thread_enabled)
138     {
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 
147         if (m_connection_sp.get() == NULL)
148         {
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.
184     lldb::ConnectionSP connection_sp (m_connection_sp);
185     if (connection_sp.get())
186     {
187         return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
188     }
189 
190     if (error_ptr)
191         error_ptr->SetErrorString("Invalid connection.");
192     status = eConnectionStatusNoConnection;
193     return 0;
194 }
195 
196 
197 size_t
198 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
199 {
200     lldb::ConnectionSP connection_sp (m_connection_sp);
201 
202     Mutex::Locker (m_write_mutex);
203     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);
212 
213     if (error_ptr)
214         error_ptr->SetErrorString("Invalid connection.");
215     status = eConnectionStatusNoConnection;
216     return 0;
217 }
218 
219 
220 bool
221 Communication::StartReadThread (Error *error_ptr)
222 {
223     if (error_ptr)
224         error_ptr->Clear();
225 
226     if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
227         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 
236     m_read_thread_enabled = true;
237     m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
238     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
239         m_read_thread_enabled = false;
240     return m_read_thread_enabled;
241 }
242 
243 bool
244 Communication::StopReadThread (Error *error_ptr)
245 {
246     if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
247         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 
256     Host::ThreadCancel (m_read_thread, error_ptr);
257 
258     bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
259     m_read_thread = LLDB_INVALID_HOST_THREAD;
260     return status;
261 }
262 
263 
264 size_t
265 Communication::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 
277         ::memcpy (dst, m_bytes.c_str(), len);
278         m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
279 
280         return len;
281     }
282     return 0;
283 }
284 
285 void
286 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
287 {
288     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
289                                  "%p Communication::AppendBytesToCache (src = %p, src_len = %zu, broadcast = %i)",
290                                  this, bytes, len, broadcast);
291     if ((bytes == NULL || len == 0)
292         && (status != lldb::eConnectionStatusEndOfFile))
293         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     }
299     else if (bytes != NULL && len > 0)
300     {
301         Mutex::Locker locker(m_bytes_mutex);
302         m_bytes.append ((const char *)bytes, len);
303         if (broadcast)
304             BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
305     }
306 }
307 
308 size_t
309 Communication::ReadFromConnection (void *dst,
310                                    size_t dst_len,
311                                    uint32_t timeout_usec,
312                                    ConnectionStatus &status,
313                                    Error *error_ptr)
314 {
315     lldb::ConnectionSP connection_sp (m_connection_sp);
316     if (connection_sp.get())
317         return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
318     return 0;
319 }
320 
321 bool
322 Communication::ReadThreadIsRunning ()
323 {
324     return m_read_thread_enabled;
325 }
326 
327 void *
328 Communication::ReadThread (void *p)
329 {
330     Communication *comm = (Communication *)p;
331 
332     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
333 
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     {
344         size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
345         if (bytes_read > 0)
346             comm->AppendBytesToCache (buf, bytes_read, true, status);
347         else if ((bytes_read == 0)
348                 && status == eConnectionStatusEndOfFile)
349         {
350             if (comm->GetCloseOnEOF ())
351                 comm->Disconnect ();
352             comm->AppendBytesToCache (buf, bytes_read, true, status);
353         }
354 
355         switch (status)
356         {
357         case eConnectionStatusSuccess:
358             break;
359 
360         case eConnectionStatusEndOfFile:
361             if (comm->GetCloseOnEOF())
362                  done = true;
363              break;
364         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
371             if (log)
372                 error.LogIfError(log.get(),
373                                  "%p Communication::ReadFromConnection () => status = %s",
374                                  p,
375                                  Communication::ConnectionStatusAsCString (status));
376             break;
377         }
378     }
379     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
380     if (log)
381         log->Printf ("%p Communication::ReadThread () thread exiting...", p);
382 
383     // Let clients know that this thread is exiting
384     comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
385     comm->m_read_thread_enabled = false;
386     comm->Disconnect();
387     return NULL;
388 }
389 
390 void
391 Communication::SetReadThreadBytesReceivedCallback
392 (
393     ReadThreadBytesReceived callback,
394     void *callback_baton
395 )
396 {
397     m_callback = callback;
398     m_callback_baton = callback_baton;
399 }
400 
401 void
402 Communication::SetConnection (Connection *connection)
403 {
404     StopReadThread(NULL);
405     Disconnect (NULL);
406     m_connection_sp.reset(connection);
407 }
408 
409 const char *
410 Communication::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";
419     case eConnectionStatusEndOfFile:      return "end of file";
420     }
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 }
426