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 
16 using namespace lldb;
17 using namespace lldb_private;
18 
19 SBCommunication::SBCommunication() : m_opaque(NULL), m_opaque_owned(false) {
20   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommunication);
21 }
22 
23 SBCommunication::SBCommunication(const char *broadcaster_name)
24     : m_opaque(new Communication(broadcaster_name)), m_opaque_owned(true) {
25   LLDB_RECORD_CONSTRUCTOR(SBCommunication, (const char *), broadcaster_name);
26 }
27 
28 SBCommunication::~SBCommunication() {
29   if (m_opaque && m_opaque_owned)
30     delete m_opaque;
31   m_opaque = NULL;
32   m_opaque_owned = false;
33 }
34 
35 bool SBCommunication::IsValid() const {
36   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommunication, IsValid);
37 
38   return m_opaque != NULL;
39 }
40 
41 bool SBCommunication::GetCloseOnEOF() {
42   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, GetCloseOnEOF);
43 
44   if (m_opaque)
45     return m_opaque->GetCloseOnEOF();
46   return false;
47 }
48 
49 void SBCommunication::SetCloseOnEOF(bool b) {
50   LLDB_RECORD_METHOD(void, SBCommunication, SetCloseOnEOF, (bool), b);
51 
52   if (m_opaque)
53     m_opaque->SetCloseOnEOF(b);
54 }
55 
56 ConnectionStatus SBCommunication::Connect(const char *url) {
57   LLDB_RECORD_METHOD(lldb::ConnectionStatus, SBCommunication, Connect,
58                      (const char *), url);
59 
60   if (m_opaque) {
61     if (!m_opaque->HasConnection())
62       m_opaque->SetConnection(Host::CreateDefaultConnection(url).release());
63     return m_opaque->Connect(url, NULL);
64   }
65   return eConnectionStatusNoConnection;
66 }
67 
68 ConnectionStatus SBCommunication::AdoptFileDesriptor(int fd, bool owns_fd) {
69   LLDB_RECORD_METHOD(lldb::ConnectionStatus, SBCommunication,
70                      AdoptFileDesriptor, (int, bool), fd, owns_fd);
71 
72   ConnectionStatus status = eConnectionStatusNoConnection;
73   if (m_opaque) {
74     if (m_opaque->HasConnection()) {
75       if (m_opaque->IsConnected())
76         m_opaque->Disconnect();
77     }
78     m_opaque->SetConnection(new ConnectionFileDescriptor(fd, owns_fd));
79     if (m_opaque->IsConnected())
80       status = eConnectionStatusSuccess;
81     else
82       status = eConnectionStatusLostConnection;
83   }
84   return status;
85 }
86 
87 ConnectionStatus SBCommunication::Disconnect() {
88   LLDB_RECORD_METHOD_NO_ARGS(lldb::ConnectionStatus, SBCommunication,
89                              Disconnect);
90 
91   ConnectionStatus status = eConnectionStatusNoConnection;
92   if (m_opaque)
93     status = m_opaque->Disconnect();
94   return status;
95 }
96 
97 bool SBCommunication::IsConnected() const {
98   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommunication, IsConnected);
99 
100   return m_opaque ? m_opaque->IsConnected() : false;
101 }
102 
103 size_t SBCommunication::Read(void *dst, size_t dst_len, uint32_t timeout_usec,
104                              ConnectionStatus &status) {
105   size_t bytes_read = 0;
106   Timeout<std::micro> timeout = timeout_usec == UINT32_MAX
107                                     ? Timeout<std::micro>(llvm::None)
108                                     : std::chrono::microseconds(timeout_usec);
109   if (m_opaque)
110     bytes_read = m_opaque->Read(dst, dst_len, timeout, status, NULL);
111   else
112     status = eConnectionStatusNoConnection;
113 
114   return bytes_read;
115 }
116 
117 size_t SBCommunication::Write(const void *src, size_t src_len,
118                               ConnectionStatus &status) {
119   size_t bytes_written = 0;
120   if (m_opaque)
121     bytes_written = m_opaque->Write(src, src_len, status, NULL);
122   else
123     status = eConnectionStatusNoConnection;
124 
125   return bytes_written;
126 }
127 
128 bool SBCommunication::ReadThreadStart() {
129   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, ReadThreadStart);
130 
131   return m_opaque ? m_opaque->StartReadThread() : false;
132 }
133 
134 bool SBCommunication::ReadThreadStop() {
135   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, ReadThreadStop);
136 
137   return m_opaque ? m_opaque->StopReadThread() : false;
138 }
139 
140 bool SBCommunication::ReadThreadIsRunning() {
141   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommunication, ReadThreadIsRunning);
142 
143   return m_opaque ? m_opaque->ReadThreadIsRunning() : false;
144 }
145 
146 bool SBCommunication::SetReadThreadBytesReceivedCallback(
147     ReadThreadBytesReceived callback, void *callback_baton) {
148   bool result = false;
149   if (m_opaque) {
150     m_opaque->SetReadThreadBytesReceivedCallback(callback, callback_baton);
151     result = true;
152   }
153   return result;
154 }
155 
156 SBBroadcaster SBCommunication::GetBroadcaster() {
157   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBCommunication,
158                              GetBroadcaster);
159 
160   SBBroadcaster broadcaster(m_opaque, false);
161   return LLDB_RECORD_RESULT(broadcaster);
162 }
163 
164 const char *SBCommunication::GetBroadcasterClass() {
165   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBCommunication,
166                                     GetBroadcasterClass);
167 
168   return Communication::GetStaticBroadcasterClass().AsCString();
169 }
170