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