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