1 //===-- Communication.h -----------------------------------------*- 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 #ifndef LLDB_CORE_COMMUNICATION_H
10 #define LLDB_CORE_COMMUNICATION_H
11 
12 #include "lldb/Utility/Timeout.h"
13 #include "lldb/lldb-defines.h"
14 #include "lldb/lldb-enumerations.h"
15 #include "lldb/lldb-forward.h"
16 #include "lldb/lldb-types.h"
17 
18 #include <mutex>
19 #include <string>
20 
21 namespace lldb_private {
22 class Connection;
23 class ConstString;
24 class Status;
25 
26 /// \class Communication Communication.h "lldb/Core/Communication.h" An
27 /// abstract communications class.
28 ///
29 /// Communication is an class that handles data communication between two data
30 /// sources. It uses a Connection class to do the real communication. This
31 /// approach has a couple of advantages: it allows a single instance of this
32 /// class to be used even though its connection can change. Connections could
33 /// negotiate for different connections based on abilities like starting with
34 /// Bluetooth and negotiating up to WiFi if available.
35 ///
36 /// When using this class, all reads and writes happen synchronously on the
37 /// calling thread. There is also a ThreadedCommunication class that supports
38 /// multi-threaded mode.
39 class Communication {
40 public:
41   /// Construct the Communication object.
42   Communication();
43 
44   /// Destructor.
45   ///
46   /// The destructor is virtual since this class gets subclassed.
47   virtual ~Communication();
48 
49   virtual void Clear();
50 
51   /// Connect using the current connection by passing \a url to its connect
52   /// function. string.
53   ///
54   /// \param[in] url
55   ///     A string that contains all information needed by the
56   ///     subclass to connect to another client.
57   ///
58   /// \return
59   ///     \b True if the connect succeeded, \b false otherwise. The
60   ///     internal error object should be filled in with an
61   ///     appropriate value based on the result of this function.
62   ///
63   /// \see Status& Communication::GetError ();
64   /// \see bool Connection::Connect (const char *url);
65   lldb::ConnectionStatus Connect(const char *url, Status *error_ptr);
66 
67   /// Disconnect the communications connection if one is currently connected.
68   ///
69   /// \return
70   ///     \b True if the disconnect succeeded, \b false otherwise. The
71   ///     internal error object should be filled in with an
72   ///     appropriate value based on the result of this function.
73   ///
74   /// \see Status& Communication::GetError ();
75   /// \see bool Connection::Disconnect ();
76   virtual lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr);
77 
78   /// Check if the connection is valid.
79   ///
80   /// \return
81   ///     \b True if this object is currently connected, \b false
82   ///     otherwise.
83   bool IsConnected() const;
84 
85   bool HasConnection() const;
86 
GetConnection()87   lldb_private::Connection *GetConnection() { return m_connection_sp.get(); }
88 
89   /// Read bytes from the current connection.
90   ///
91   /// If no read thread is running, this function call the connection's
92   /// Connection::Read(...) function to get any available.
93   ///
94   /// \param[in] dst
95   ///     A destination buffer that must be at least \a dst_len bytes
96   ///     long.
97   ///
98   /// \param[in] dst_len
99   ///     The number of bytes to attempt to read, and also the max
100   ///     number of bytes that can be placed into \a dst.
101   ///
102   /// \param[in] timeout
103   ///     A timeout value or std::nullopt for no timeout.
104   ///
105   /// \return
106   ///     The number of bytes actually read.
107   ///
108   /// \see size_t Connection::Read (void *, size_t);
109   virtual size_t Read(void *dst, size_t dst_len,
110                       const Timeout<std::micro> &timeout,
111                       lldb::ConnectionStatus &status, Status *error_ptr);
112 
113   /// The actual write function that attempts to write to the communications
114   /// protocol.
115   ///
116   /// Subclasses must override this function.
117   ///
118   /// \param[in] src
119   ///     A source buffer that must be at least \a src_len bytes
120   ///     long.
121   ///
122   /// \param[in] src_len
123   ///     The number of bytes to attempt to write, and also the
124   ///     number of bytes are currently available in \a src.
125   ///
126   /// \return
127   ///     The number of bytes actually Written.
128   size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status,
129                Status *error_ptr);
130 
131   /// Repeatedly attempt writing until either \a src_len bytes are written
132   /// or a permanent failure occurs.
133   ///
134   /// \param[in] src
135   ///     A source buffer that must be at least \a src_len bytes
136   ///     long.
137   ///
138   /// \param[in] src_len
139   ///     The number of bytes to attempt to write, and also the
140   ///     number of bytes are currently available in \a src.
141   ///
142   /// \return
143   ///     The number of bytes actually Written.
144   size_t WriteAll(const void *src, size_t src_len,
145                   lldb::ConnectionStatus &status, Status *error_ptr);
146 
147   /// Sets the connection that it to be used by this class.
148   ///
149   /// By making a communication class that uses different connections it
150   /// allows a single communication interface to negotiate and change its
151   /// connection without any interruption to the client. It also allows the
152   /// Communication class to be subclassed for packet based communication.
153   ///
154   /// \param[in] connection
155   ///     A connection that this class will own and destroy.
156   ///
157   /// \see
158   ///     class Connection
159   virtual void SetConnection(std::unique_ptr<Connection> connection);
160 
161   static std::string ConnectionStatusAsString(lldb::ConnectionStatus status);
162 
GetCloseOnEOF()163   bool GetCloseOnEOF() const { return m_close_on_eof; }
164 
SetCloseOnEOF(bool b)165   void SetCloseOnEOF(bool b) { m_close_on_eof = b; }
166 
167 protected:
168   lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use
169                                       ///by this communications class.
170   std::mutex
171       m_write_mutex; ///< Don't let multiple threads write at the same time...
172   bool m_close_on_eof;
173 
174   size_t ReadFromConnection(void *dst, size_t dst_len,
175                             const Timeout<std::micro> &timeout,
176                             lldb::ConnectionStatus &status, Status *error_ptr);
177 
178 private:
179   Communication(const Communication &) = delete;
180   const Communication &operator=(const Communication &) = delete;
181 };
182 
183 } // namespace lldb_private
184 
185 #endif // LLDB_CORE_COMMUNICATION_H
186