1 //===-- SBCommunication.cpp -------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/API/SBCommunication.h"
10 #include "SBReproducerPrivate.h"
11 #include "lldb/API/SBBroadcaster.h"
12 #include "lldb/Core/Communication.h"
13 #include "lldb/Host/ConnectionFileDescriptor.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Utility/Log.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 SBCommunication::SBCommunication() : m_opaque(NULL), m_opaque_owned(false) {
21   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommunication);
22 }
23 
24 SBCommunication::SBCommunication(const char *broadcaster_name)
25     : m_opaque(new Communication(broadcaster_name)), m_opaque_owned(true) {
26   LLDB_RECORD_CONSTRUCTOR(SBCommunication, (const char *), broadcaster_name);
27 
28   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
29 
30   if (log)
31     log->Printf("SBCommunication::SBCommunication (broadcaster_name=\"%s\") => "
32                 "SBCommunication(%p)",
33                 broadcaster_name, static_cast<void *>(m_opaque));
34 }
35 
36 SBCommunication::~SBCommunication() {
37   if (m_opaque && m_opaque_owned)
38     delete m_opaque;
39   m_opaque = NULL;
40   m_opaque_owned = false;
41 }
42 
43 bool SBCommunication::IsValid() const {
44   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommunication, IsValid);
45 
46   return m_opaque != NULL;
47 }
48 
49 bool SBCommunication::GetCloseOnEOF() {
50   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, GetCloseOnEOF);
51 
52   if (m_opaque)
53     return m_opaque->GetCloseOnEOF();
54   return false;
55 }
56 
57 void SBCommunication::SetCloseOnEOF(bool b) {
58   LLDB_RECORD_METHOD(void, SBCommunication, SetCloseOnEOF, (bool), b);
59 
60   if (m_opaque)
61     m_opaque->SetCloseOnEOF(b);
62 }
63 
64 ConnectionStatus SBCommunication::Connect(const char *url) {
65   LLDB_RECORD_METHOD(lldb::ConnectionStatus, SBCommunication, Connect,
66                      (const char *), url);
67 
68   if (m_opaque) {
69     if (!m_opaque->HasConnection())
70       m_opaque->SetConnection(Host::CreateDefaultConnection(url).release());
71     return m_opaque->Connect(url, NULL);
72   }
73   return eConnectionStatusNoConnection;
74 }
75 
76 ConnectionStatus SBCommunication::AdoptFileDesriptor(int fd, bool owns_fd) {
77   LLDB_RECORD_METHOD(lldb::ConnectionStatus, SBCommunication,
78                      AdoptFileDesriptor, (int, bool), fd, owns_fd);
79 
80   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
81 
82   ConnectionStatus status = eConnectionStatusNoConnection;
83   if (m_opaque) {
84     if (m_opaque->HasConnection()) {
85       if (m_opaque->IsConnected())
86         m_opaque->Disconnect();
87     }
88     m_opaque->SetConnection(new ConnectionFileDescriptor(fd, owns_fd));
89     if (m_opaque->IsConnected())
90       status = eConnectionStatusSuccess;
91     else
92       status = eConnectionStatusLostConnection;
93   }
94 
95   if (log)
96     log->Printf(
97         "SBCommunication(%p)::AdoptFileDescriptor (fd=%d, ownd_fd=%i) => %s",
98         static_cast<void *>(m_opaque), fd, owns_fd,
99         Communication::ConnectionStatusAsCString(status));
100 
101   return status;
102 }
103 
104 ConnectionStatus SBCommunication::Disconnect() {
105   LLDB_RECORD_METHOD_NO_ARGS(lldb::ConnectionStatus, SBCommunication,
106                              Disconnect);
107 
108   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
109 
110   ConnectionStatus status = eConnectionStatusNoConnection;
111   if (m_opaque)
112     status = m_opaque->Disconnect();
113 
114   if (log)
115     log->Printf("SBCommunication(%p)::Disconnect () => %s",
116                 static_cast<void *>(m_opaque),
117                 Communication::ConnectionStatusAsCString(status));
118 
119   return status;
120 }
121 
122 bool SBCommunication::IsConnected() const {
123   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommunication, IsConnected);
124 
125   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
126   bool result = false;
127   if (m_opaque)
128     result = m_opaque->IsConnected();
129 
130   if (log)
131     log->Printf("SBCommunication(%p)::IsConnected () => %i",
132                 static_cast<void *>(m_opaque), result);
133 
134   return false;
135 }
136 
137 size_t SBCommunication::Read(void *dst, size_t dst_len, uint32_t timeout_usec,
138                              ConnectionStatus &status) {
139   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
140   if (log)
141     log->Printf("SBCommunication(%p)::Read (dst=%p, dst_len=%" PRIu64
142                 ", timeout_usec=%u, &status)...",
143                 static_cast<void *>(m_opaque), static_cast<void *>(dst),
144                 static_cast<uint64_t>(dst_len), timeout_usec);
145   size_t bytes_read = 0;
146   Timeout<std::micro> timeout = timeout_usec == UINT32_MAX
147                                     ? Timeout<std::micro>(llvm::None)
148                                     : std::chrono::microseconds(timeout_usec);
149   if (m_opaque)
150     bytes_read = m_opaque->Read(dst, dst_len, timeout, status, NULL);
151   else
152     status = eConnectionStatusNoConnection;
153 
154   if (log)
155     log->Printf("SBCommunication(%p)::Read (dst=%p, dst_len=%" PRIu64
156                 ", timeout_usec=%u, &status=%s) => %" PRIu64,
157                 static_cast<void *>(m_opaque), static_cast<void *>(dst),
158                 static_cast<uint64_t>(dst_len), timeout_usec,
159                 Communication::ConnectionStatusAsCString(status),
160                 static_cast<uint64_t>(bytes_read));
161   return bytes_read;
162 }
163 
164 size_t SBCommunication::Write(const void *src, size_t src_len,
165                               ConnectionStatus &status) {
166   size_t bytes_written = 0;
167   if (m_opaque)
168     bytes_written = m_opaque->Write(src, src_len, status, NULL);
169   else
170     status = eConnectionStatusNoConnection;
171 
172   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
173   if (log)
174     log->Printf("SBCommunication(%p)::Write (src=%p, src_len=%" PRIu64
175                 ", &status=%s) => %" PRIu64,
176                 static_cast<void *>(m_opaque), static_cast<const void *>(src),
177                 static_cast<uint64_t>(src_len),
178                 Communication::ConnectionStatusAsCString(status),
179                 static_cast<uint64_t>(bytes_written));
180 
181   return 0;
182 }
183 
184 bool SBCommunication::ReadThreadStart() {
185   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, ReadThreadStart);
186 
187   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
188 
189   bool success = false;
190   if (m_opaque)
191     success = m_opaque->StartReadThread();
192 
193   if (log)
194     log->Printf("SBCommunication(%p)::ReadThreadStart () => %i",
195                 static_cast<void *>(m_opaque), success);
196 
197   return success;
198 }
199 
200 bool SBCommunication::ReadThreadStop() {
201   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, ReadThreadStop);
202 
203   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
204   if (log)
205     log->Printf("SBCommunication(%p)::ReadThreadStop ()...",
206                 static_cast<void *>(m_opaque));
207 
208   bool success = false;
209   if (m_opaque)
210     success = m_opaque->StopReadThread();
211 
212   if (log)
213     log->Printf("SBCommunication(%p)::ReadThreadStop () => %i",
214                 static_cast<void *>(m_opaque), success);
215 
216   return success;
217 }
218 
219 bool SBCommunication::ReadThreadIsRunning() {
220   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, ReadThreadIsRunning);
221 
222   bool result = false;
223   if (m_opaque)
224     result = m_opaque->ReadThreadIsRunning();
225   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
226   if (log)
227     log->Printf("SBCommunication(%p)::ReadThreadIsRunning () => %i",
228                 static_cast<void *>(m_opaque), result);
229   return result;
230 }
231 
232 bool SBCommunication::SetReadThreadBytesReceivedCallback(
233     ReadThreadBytesReceived callback, void *callback_baton) {
234   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
235 
236   bool result = false;
237   if (m_opaque) {
238     m_opaque->SetReadThreadBytesReceivedCallback(callback, callback_baton);
239     result = true;
240   }
241 
242   if (log)
243     log->Printf("SBCommunication(%p)::SetReadThreadBytesReceivedCallback "
244                 "(callback=%p, baton=%p) => %i",
245                 static_cast<void *>(m_opaque),
246                 reinterpret_cast<void *>(reinterpret_cast<intptr_t>(callback)),
247                 static_cast<void *>(callback_baton), result);
248 
249   return result;
250 }
251 
252 SBBroadcaster SBCommunication::GetBroadcaster() {
253   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBCommunication,
254                              GetBroadcaster);
255 
256   SBBroadcaster broadcaster(m_opaque, false);
257 
258   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
259 
260   if (log)
261     log->Printf("SBCommunication(%p)::GetBroadcaster () => SBBroadcaster (%p)",
262                 static_cast<void *>(m_opaque),
263                 static_cast<void *>(broadcaster.get()));
264 
265   return LLDB_RECORD_RESULT(broadcaster);
266 }
267 
268 const char *SBCommunication::GetBroadcasterClass() {
269   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBCommunication,
270                                     GetBroadcasterClass);
271 
272   return Communication::GetStaticBroadcasterClass().AsCString();
273 }
274 
275 //
276 // void
277 // SBCommunication::CreateIfNeeded ()
278 //{
279 //    if (m_opaque == NULL)
280 //    {
281 //        static uint32_t g_broadcaster_num;
282 //        char broadcaster_name[256];
283 //        ::snprintf (name, broadcaster_name, "%p SBCommunication", this);
284 //        m_opaque = new Communication (broadcaster_name);
285 //        m_opaque_owned = true;
286 //    }
287 //    assert (m_opaque);
288 //}
289 //
290 //
291