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