1254721Semaste//===-- Communication.cpp ---------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste// C Includes
11254721Semaste// C++ Includes
12254721Semaste// Other libraries and framework includes
13254721Semaste// Project includes
14254721Semaste#include "lldb/lldb-private-log.h"
15254721Semaste#include "lldb/Core/Communication.h"
16254721Semaste#include "lldb/Core/Connection.h"
17254721Semaste#include "lldb/Core/Log.h"
18254721Semaste#include "lldb/Core/Timer.h"
19254721Semaste#include "lldb/Core/Event.h"
20254721Semaste#include "lldb/Host/Host.h"
21254721Semaste#include <string.h>
22254721Semaste
23254721Semasteusing namespace lldb;
24254721Semasteusing namespace lldb_private;
25254721Semaste
26254721SemasteConstString &
27254721SemasteCommunication::GetStaticBroadcasterClass ()
28254721Semaste{
29254721Semaste    static ConstString class_name ("lldb.communication");
30254721Semaste    return class_name;
31254721Semaste}
32254721Semaste
33254721Semaste//----------------------------------------------------------------------
34254721Semaste// Constructor
35254721Semaste//----------------------------------------------------------------------
36254721SemasteCommunication::Communication(const char *name) :
37254721Semaste    Broadcaster (NULL, name),
38254721Semaste    m_connection_sp (),
39254721Semaste    m_read_thread (LLDB_INVALID_HOST_THREAD),
40254721Semaste    m_read_thread_enabled (false),
41254721Semaste    m_bytes(),
42254721Semaste    m_bytes_mutex (Mutex::eMutexTypeRecursive),
43254721Semaste    m_write_mutex (Mutex::eMutexTypeNormal),
44254721Semaste    m_callback (NULL),
45254721Semaste    m_callback_baton (NULL),
46254721Semaste    m_close_on_eof (true)
47254721Semaste
48254721Semaste{
49254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
50254721Semaste                                 "%p Communication::Communication (name = %s)",
51254721Semaste                                 this, name);
52254721Semaste
53254721Semaste    SetEventName (eBroadcastBitDisconnected, "disconnected");
54254721Semaste    SetEventName (eBroadcastBitReadThreadGotBytes, "got bytes");
55254721Semaste    SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
56254721Semaste    SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
57254721Semaste    SetEventName (eBroadcastBitPacketAvailable, "packet available");
58254721Semaste
59254721Semaste    CheckInWithManager();
60254721Semaste}
61254721Semaste
62254721Semaste//----------------------------------------------------------------------
63254721Semaste// Destructor
64254721Semaste//----------------------------------------------------------------------
65254721SemasteCommunication::~Communication()
66254721Semaste{
67254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
68254721Semaste                                 "%p Communication::~Communication (name = %s)",
69254721Semaste                                 this, m_broadcaster_name.AsCString(""));
70254721Semaste    Clear();
71254721Semaste}
72254721Semaste
73254721Semastevoid
74254721SemasteCommunication::Clear()
75254721Semaste{
76254721Semaste    SetReadThreadBytesReceivedCallback (NULL, NULL);
77254721Semaste    Disconnect (NULL);
78254721Semaste    StopReadThread (NULL);
79254721Semaste}
80254721Semaste
81254721SemasteConnectionStatus
82254721SemasteCommunication::Connect (const char *url, Error *error_ptr)
83254721Semaste{
84254721Semaste    Clear();
85254721Semaste
86254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
87254721Semaste
88254721Semaste    lldb::ConnectionSP connection_sp (m_connection_sp);
89254721Semaste    if (connection_sp.get())
90254721Semaste        return connection_sp->Connect (url, error_ptr);
91254721Semaste    if (error_ptr)
92254721Semaste        error_ptr->SetErrorString("Invalid connection.");
93254721Semaste    return eConnectionStatusNoConnection;
94254721Semaste}
95254721Semaste
96254721SemasteConnectionStatus
97254721SemasteCommunication::Disconnect (Error *error_ptr)
98254721Semaste{
99254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
100254721Semaste
101254721Semaste    lldb::ConnectionSP connection_sp (m_connection_sp);
102254721Semaste    if (connection_sp.get())
103254721Semaste    {
104254721Semaste        ConnectionStatus status = connection_sp->Disconnect (error_ptr);
105254721Semaste        // We currently don't protect connection_sp with any mutex for
106254721Semaste        // multi-threaded environments. So lets not nuke our connection class
107254721Semaste        // without putting some multi-threaded protections in. We also probably
108254721Semaste        // don't want to pay for the overhead it might cause if every time we
109254721Semaste        // access the connection we have to take a lock.
110254721Semaste        //
111254721Semaste        // This unique pointer will cleanup after itself when this object goes away,
112254721Semaste        // so there is no need to currently have it destroy itself immediately
113254721Semaste        // upon disconnnect.
114254721Semaste        //connection_sp.reset();
115254721Semaste        return status;
116254721Semaste    }
117254721Semaste    return eConnectionStatusNoConnection;
118254721Semaste}
119254721Semaste
120254721Semastebool
121254721SemasteCommunication::IsConnected () const
122254721Semaste{
123254721Semaste    lldb::ConnectionSP connection_sp (m_connection_sp);
124254721Semaste    if (connection_sp.get())
125254721Semaste        return connection_sp->IsConnected ();
126254721Semaste    return false;
127254721Semaste}
128254721Semaste
129254721Semastebool
130254721SemasteCommunication::HasConnection () const
131254721Semaste{
132254721Semaste    return m_connection_sp.get() != NULL;
133254721Semaste}
134254721Semaste
135254721Semastesize_t
136254721SemasteCommunication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
137254721Semaste{
138254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
139254721Semaste                                         "%p Communication::Read (dst = %p, dst_len = %" PRIu64 ", timeout = %u usec) connection = %p",
140254721Semaste                                         this,
141254721Semaste                                         dst,
142254721Semaste                                         (uint64_t)dst_len,
143254721Semaste                                         timeout_usec,
144254721Semaste                                         m_connection_sp.get());
145254721Semaste
146254721Semaste    if (m_read_thread_enabled)
147254721Semaste    {
148254721Semaste        // We have a dedicated read thread that is getting data for us
149254721Semaste        size_t cached_bytes = GetCachedBytes (dst, dst_len);
150254721Semaste        if (cached_bytes > 0 || timeout_usec == 0)
151254721Semaste        {
152254721Semaste            status = eConnectionStatusSuccess;
153254721Semaste            return cached_bytes;
154254721Semaste        }
155254721Semaste
156254721Semaste        if (m_connection_sp.get() == NULL)
157254721Semaste        {
158254721Semaste            if (error_ptr)
159254721Semaste                error_ptr->SetErrorString("Invalid connection.");
160254721Semaste            status = eConnectionStatusNoConnection;
161254721Semaste            return 0;
162254721Semaste        }
163254721Semaste        // Set the timeout appropriately
164254721Semaste        TimeValue timeout_time;
165254721Semaste        if (timeout_usec != UINT32_MAX)
166254721Semaste        {
167254721Semaste            timeout_time = TimeValue::Now();
168254721Semaste            timeout_time.OffsetWithMicroSeconds (timeout_usec);
169254721Semaste        }
170254721Semaste
171254721Semaste        Listener listener ("Communication::Read");
172254721Semaste        listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
173254721Semaste        EventSP event_sp;
174254721Semaste        while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
175254721Semaste        {
176254721Semaste            const uint32_t event_type = event_sp->GetType();
177254721Semaste            if (event_type & eBroadcastBitReadThreadGotBytes)
178254721Semaste            {
179254721Semaste                return GetCachedBytes (dst, dst_len);
180254721Semaste            }
181254721Semaste
182254721Semaste            if (event_type & eBroadcastBitReadThreadDidExit)
183254721Semaste            {
184254721Semaste                Disconnect (NULL);
185254721Semaste                break;
186254721Semaste            }
187254721Semaste        }
188254721Semaste        return 0;
189254721Semaste    }
190254721Semaste
191254721Semaste    // We aren't using a read thread, just read the data synchronously in this
192254721Semaste    // thread.
193254721Semaste    lldb::ConnectionSP connection_sp (m_connection_sp);
194254721Semaste    if (connection_sp.get())
195254721Semaste    {
196254721Semaste        return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
197254721Semaste    }
198254721Semaste
199254721Semaste    if (error_ptr)
200254721Semaste        error_ptr->SetErrorString("Invalid connection.");
201254721Semaste    status = eConnectionStatusNoConnection;
202254721Semaste    return 0;
203254721Semaste}
204254721Semaste
205254721Semaste
206254721Semastesize_t
207254721SemasteCommunication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
208254721Semaste{
209254721Semaste    lldb::ConnectionSP connection_sp (m_connection_sp);
210254721Semaste
211254721Semaste    Mutex::Locker locker(m_write_mutex);
212254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
213254721Semaste                                         "%p Communication::Write (src = %p, src_len = %" PRIu64 ") connection = %p",
214254721Semaste                                         this,
215254721Semaste                                         src,
216254721Semaste                                         (uint64_t)src_len,
217254721Semaste                                         connection_sp.get());
218254721Semaste
219254721Semaste    if (connection_sp.get())
220254721Semaste        return connection_sp->Write (src, src_len, status, error_ptr);
221254721Semaste
222254721Semaste    if (error_ptr)
223254721Semaste        error_ptr->SetErrorString("Invalid connection.");
224254721Semaste    status = eConnectionStatusNoConnection;
225254721Semaste    return 0;
226254721Semaste}
227254721Semaste
228254721Semaste
229254721Semastebool
230254721SemasteCommunication::StartReadThread (Error *error_ptr)
231254721Semaste{
232254721Semaste    if (error_ptr)
233254721Semaste        error_ptr->Clear();
234254721Semaste
235254721Semaste    if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
236254721Semaste        return true;
237254721Semaste
238254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
239254721Semaste                                 "%p Communication::StartReadThread ()", this);
240254721Semaste
241254721Semaste
242254721Semaste    char thread_name[1024];
243254721Semaste    snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
244254721Semaste
245254721Semaste    m_read_thread_enabled = true;
246254721Semaste    m_read_thread = Host::ThreadCreate (thread_name, Communication::ReadThread, this, error_ptr);
247254721Semaste    if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
248254721Semaste        m_read_thread_enabled = false;
249254721Semaste    return m_read_thread_enabled;
250254721Semaste}
251254721Semaste
252254721Semastebool
253254721SemasteCommunication::StopReadThread (Error *error_ptr)
254254721Semaste{
255254721Semaste    if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
256254721Semaste        return true;
257254721Semaste
258254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
259254721Semaste                                 "%p Communication::StopReadThread ()", this);
260254721Semaste
261254721Semaste    m_read_thread_enabled = false;
262254721Semaste
263254721Semaste    BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
264254721Semaste
265254721Semaste    //Host::ThreadCancel (m_read_thread, error_ptr);
266254721Semaste
267254721Semaste    bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
268254721Semaste    m_read_thread = LLDB_INVALID_HOST_THREAD;
269254721Semaste    return status;
270254721Semaste}
271254721Semaste
272254721Semaste
273254721Semastesize_t
274254721SemasteCommunication::GetCachedBytes (void *dst, size_t dst_len)
275254721Semaste{
276254721Semaste    Mutex::Locker locker(m_bytes_mutex);
277254721Semaste    if (m_bytes.size() > 0)
278254721Semaste    {
279254721Semaste        // If DST is NULL and we have a thread, then return the number
280254721Semaste        // of bytes that are available so the caller can call again
281254721Semaste        if (dst == NULL)
282254721Semaste            return m_bytes.size();
283254721Semaste
284254721Semaste        const size_t len = std::min<size_t>(dst_len, m_bytes.size());
285254721Semaste
286254721Semaste        ::memcpy (dst, m_bytes.c_str(), len);
287254721Semaste        m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
288254721Semaste
289254721Semaste        return len;
290254721Semaste    }
291254721Semaste    return 0;
292254721Semaste}
293254721Semaste
294254721Semastevoid
295254721SemasteCommunication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
296254721Semaste{
297254721Semaste    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
298254721Semaste                                 "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 ", broadcast = %i)",
299254721Semaste                                 this, bytes, (uint64_t)len, broadcast);
300254721Semaste    if ((bytes == NULL || len == 0)
301254721Semaste        && (status != lldb::eConnectionStatusEndOfFile))
302254721Semaste        return;
303254721Semaste    if (m_callback)
304254721Semaste    {
305254721Semaste        // If the user registered a callback, then call it and do not broadcast
306254721Semaste        m_callback (m_callback_baton, bytes, len);
307254721Semaste    }
308254721Semaste    else if (bytes != NULL && len > 0)
309254721Semaste    {
310254721Semaste        Mutex::Locker locker(m_bytes_mutex);
311254721Semaste        m_bytes.append ((const char *)bytes, len);
312254721Semaste        if (broadcast)
313254721Semaste            BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
314254721Semaste    }
315254721Semaste}
316254721Semaste
317254721Semastesize_t
318254721SemasteCommunication::ReadFromConnection (void *dst,
319254721Semaste                                   size_t dst_len,
320254721Semaste                                   uint32_t timeout_usec,
321254721Semaste                                   ConnectionStatus &status,
322254721Semaste                                   Error *error_ptr)
323254721Semaste{
324254721Semaste    lldb::ConnectionSP connection_sp (m_connection_sp);
325254721Semaste    if (connection_sp.get())
326254721Semaste        return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
327254721Semaste    return 0;
328254721Semaste}
329254721Semaste
330254721Semastebool
331254721SemasteCommunication::ReadThreadIsRunning ()
332254721Semaste{
333254721Semaste    return m_read_thread_enabled;
334254721Semaste}
335254721Semaste
336254721Semastevoid *
337254721SemasteCommunication::ReadThread (void *p)
338254721Semaste{
339254721Semaste    Communication *comm = (Communication *)p;
340254721Semaste
341254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
342254721Semaste
343254721Semaste    if (log)
344254721Semaste        log->Printf ("%p Communication::ReadThread () thread starting...", p);
345254721Semaste
346254721Semaste    uint8_t buf[1024];
347254721Semaste
348254721Semaste    Error error;
349254721Semaste    ConnectionStatus status = eConnectionStatusSuccess;
350254721Semaste    bool done = false;
351254721Semaste    while (!done && comm->m_read_thread_enabled)
352254721Semaste    {
353254721Semaste        size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
354254721Semaste        if (bytes_read > 0)
355254721Semaste            comm->AppendBytesToCache (buf, bytes_read, true, status);
356254721Semaste        else if ((bytes_read == 0)
357254721Semaste                && status == eConnectionStatusEndOfFile)
358254721Semaste        {
359254721Semaste            if (comm->GetCloseOnEOF ())
360254721Semaste                comm->Disconnect ();
361254721Semaste            comm->AppendBytesToCache (buf, bytes_read, true, status);
362254721Semaste        }
363254721Semaste
364254721Semaste        switch (status)
365254721Semaste        {
366254721Semaste        case eConnectionStatusSuccess:
367254721Semaste            break;
368254721Semaste
369254721Semaste        case eConnectionStatusEndOfFile:
370254721Semaste            if (comm->GetCloseOnEOF())
371254721Semaste                 done = true;
372254721Semaste             break;
373254721Semaste        case eConnectionStatusNoConnection:     // No connection
374254721Semaste        case eConnectionStatusLostConnection:   // Lost connection while connected to a valid connection
375254721Semaste            done = true;
376254721Semaste            // Fall through...
377254721Semaste        case eConnectionStatusError:            // Check GetError() for details
378254721Semaste        case eConnectionStatusTimedOut:         // Request timed out
379254721Semaste            if (log)
380254721Semaste                error.LogIfError (log,
381254721Semaste                                  "%p Communication::ReadFromConnection () => status = %s",
382254721Semaste                                  p,
383254721Semaste                                  Communication::ConnectionStatusAsCString (status));
384254721Semaste            break;
385254721Semaste        }
386254721Semaste    }
387254721Semaste    log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
388254721Semaste    if (log)
389254721Semaste        log->Printf ("%p Communication::ReadThread () thread exiting...", p);
390254721Semaste
391254721Semaste    // Let clients know that this thread is exiting
392254721Semaste    comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
393254721Semaste    return NULL;
394254721Semaste}
395254721Semaste
396254721Semastevoid
397254721SemasteCommunication::SetReadThreadBytesReceivedCallback
398254721Semaste(
399254721Semaste    ReadThreadBytesReceived callback,
400254721Semaste    void *callback_baton
401254721Semaste)
402254721Semaste{
403254721Semaste    m_callback = callback;
404254721Semaste    m_callback_baton = callback_baton;
405254721Semaste}
406254721Semaste
407254721Semastevoid
408254721SemasteCommunication::SetConnection (Connection *connection)
409254721Semaste{
410254721Semaste    Disconnect (NULL);
411254721Semaste    StopReadThread(NULL);
412254721Semaste    m_connection_sp.reset(connection);
413254721Semaste}
414254721Semaste
415254721Semasteconst char *
416254721SemasteCommunication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
417254721Semaste{
418254721Semaste    switch (status)
419254721Semaste    {
420254721Semaste    case eConnectionStatusSuccess:        return "success";
421254721Semaste    case eConnectionStatusError:          return "error";
422254721Semaste    case eConnectionStatusTimedOut:       return "timed out";
423254721Semaste    case eConnectionStatusNoConnection:   return "no connection";
424254721Semaste    case eConnectionStatusLostConnection: return "lost connection";
425254721Semaste    case eConnectionStatusEndOfFile:      return "end of file";
426254721Semaste    }
427254721Semaste
428254721Semaste    static char unknown_state_string[64];
429254721Semaste    snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
430254721Semaste    return unknown_state_string;
431254721Semaste}
432