summaryrefslogtreecommitdiffstats
path: root/include/lldb/Core/Communication.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/lldb/Core/Communication.h')
-rw-r--r--include/lldb/Core/Communication.h413
1 files changed, 413 insertions, 0 deletions
diff --git a/include/lldb/Core/Communication.h b/include/lldb/Core/Communication.h
new file mode 100644
index 0000000..98d4dfd
--- /dev/null
+++ b/include/lldb/Core/Communication.h
@@ -0,0 +1,413 @@
+//===-- Communication.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Communication_h_
+#define liblldb_Communication_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class Communication Communication.h "lldb/Core/Communication.h"
+/// @brief An abstract communications class.
+///
+/// Communication is an class that handles data communication
+/// between two data sources. It uses a Connection class to do the
+/// real communication. This approach has a couple of advantages: it
+/// allows a single instance of this class to be used even though its
+/// connection can change. Connections could negotiate for different
+/// connections based on abilities like starting with Bluetooth and
+/// negotiating up to WiFi if available. It also allows this class to be
+/// subclassed by any interfaces that don't want to give bytes but want
+/// to validate and give out packets. This can be done by overriding:
+///
+/// AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast);
+///
+/// Communication inherits from Broadcaster which means it can be
+/// used in conjunction with Listener to wait for multiple broadcaster
+/// objects and multiple events from each of those objects.
+/// Communication defines a set of pre-defined event bits (see
+/// enumerations definitions that start with "eBroadcastBit" below).
+///
+/// There are two modes in which communications can occur:
+/// @li single-threaded
+/// @li multi-threaded
+///
+/// In single-threaded mode, all reads and writes happen synchronously
+/// on the calling thread.
+///
+/// In multi-threaded mode, a read thread is spawned that continually
+/// reads data and caches any received bytes. To start the read thread
+/// clients call:
+///
+/// bool Communication::StartReadThread (Error *);
+///
+/// If true is returned a read thead has been spawned that will
+/// continually execute a call to the pure virtual DoRead function:
+///
+/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t);
+///
+/// When bytes are received the data gets cached in \a m_bytes and this
+/// class will broadcast a \b eBroadcastBitReadThreadGotBytes event.
+/// Clients that want packet based communication should override
+/// AppendBytesToCache. The subclasses can choose to call the
+/// built in AppendBytesToCache with the \a broadcast parameter set to
+/// false. This will cause the \b eBroadcastBitReadThreadGotBytes event
+/// not get broadcast, and then the subclass can post a \b
+/// eBroadcastBitPacketAvailable event when a full packet of data has
+/// been received.
+///
+/// If the connection is disconnected a \b eBroadcastBitDisconnected
+/// event gets broadcast. If the read thread exits a \b
+/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients
+/// can also post a \b eBroadcastBitReadThreadShouldExit event to this
+/// object which will cause the read thread to exit.
+//----------------------------------------------------------------------
+class Communication : public Broadcaster
+{
+public:
+ enum {
+ eBroadcastBitDisconnected = (1 << 0), ///< Sent when the communications connection is lost.
+ eBroadcastBitReadThreadGotBytes = (1 << 1), ///< Sent by the read thread when bytes become available.
+ eBroadcastBitReadThreadDidExit = (1 << 2), ///< Sent by the read thread when it exits to inform clients.
+ eBroadcastBitReadThreadShouldExit = (1 << 3), ///< Sent by clients that need to cancel the read thread.
+ eBroadcastBitPacketAvailable = (1 << 4), ///< Sent when data received makes a complete packet.
+ kLoUserBroadcastBit = (1 << 16),///< Subclasses can used bits 31:16 for any needed events.
+ kHiUserBroadcastBit = (1 << 31),
+ eAllEventBits = 0xffffffff
+ };
+
+ typedef void (*ReadThreadBytesReceived) (void *baton, const void *src, size_t src_len);
+
+
+ //------------------------------------------------------------------
+ /// Construct the Communication object with the specified name for
+ /// the Broadcaster that this object inherits from.
+ ///
+ /// @param[in] broadcaster_name
+ /// The name of the broadcaster object. This name should be as
+ /// complete as possible to uniquely identify this object. The
+ /// broadcaster name can be updated after the connect function
+ /// is called.
+ //------------------------------------------------------------------
+ Communication(const char * broadcaster_name);
+
+ //------------------------------------------------------------------
+ /// Destructor.
+ ///
+ /// The destructor is virtual since this class gets subclassed.
+ //------------------------------------------------------------------
+ virtual
+ ~Communication();
+
+ void
+ Clear ();
+
+ //------------------------------------------------------------------
+ /// Connect using the current connection by passing \a url to its
+ /// connect function.
+ /// string.
+ ///
+ /// @param[in] url
+ /// A string that contains all information needed by the
+ /// subclass to connect to another client.
+ ///
+ /// @return
+ /// \b True if the connect succeeded, \b false otherwise. The
+ /// internal error object should be filled in with an
+ /// appropriate value based on the result of this function.
+ ///
+ /// @see Error& Communication::GetError ();
+ /// @see bool Connection::Connect (const char *url);
+ //------------------------------------------------------------------
+ lldb::ConnectionStatus
+ Connect (const char *url, Error *error_ptr);
+
+ //------------------------------------------------------------------
+ /// Disconnect the communications connection if one is currently
+ /// connected.
+ ///
+ /// @return
+ /// \b True if the disconnect succeeded, \b false otherwise. The
+ /// internal error object should be filled in with an
+ /// appropriate value based on the result of this function.
+ ///
+ /// @see Error& Communication::GetError ();
+ /// @see bool Connection::Disconnect ();
+ //------------------------------------------------------------------
+ lldb::ConnectionStatus
+ Disconnect (Error *error_ptr = NULL);
+
+ //------------------------------------------------------------------
+ /// Check if the connection is valid.
+ ///
+ /// @return
+ /// \b True if this object is currently connected, \b false
+ /// otherwise.
+ //------------------------------------------------------------------
+ bool
+ IsConnected () const;
+
+ bool
+ HasConnection () const;
+
+ lldb_private::Connection *
+ GetConnection ()
+ {
+ return m_connection_sp.get();
+ }
+ //------------------------------------------------------------------
+ /// Read bytes from the current connection.
+ ///
+ /// If no read thread is running, this function call the
+ /// connection's Connection::Read(...) function to get any available.
+ ///
+ /// If a read thread has been started, this function will check for
+ /// any cached bytes that have already been read and return any
+ /// currently available bytes. If no bytes are cached, it will wait
+ /// for the bytes to become available by listening for the \a
+ /// eBroadcastBitReadThreadGotBytes event. If this function consumes
+ /// all of the bytes in the cache, it will reset the
+ /// \a eBroadcastBitReadThreadGotBytes event bit.
+ ///
+ /// @param[in] dst
+ /// A destination buffer that must be at least \a dst_len bytes
+ /// long.
+ ///
+ /// @param[in] dst_len
+ /// The number of bytes to attempt to read, and also the max
+ /// number of bytes that can be placed into \a dst.
+ ///
+ /// @param[in] timeout_usec
+ /// A timeout value in micro-seconds.
+ ///
+ /// @return
+ /// The number of bytes actually read.
+ ///
+ /// @see size_t Connection::Read (void *, size_t);
+ //------------------------------------------------------------------
+ size_t
+ Read (void *dst,
+ size_t dst_len,
+ uint32_t timeout_usec,
+ lldb::ConnectionStatus &status,
+ Error *error_ptr);
+
+ //------------------------------------------------------------------
+ /// The actual write function that attempts to write to the
+ /// communications protocol.
+ ///
+ /// Subclasses must override this function.
+ ///
+ /// @param[in] src
+ /// A source buffer that must be at least \a src_len bytes
+ /// long.
+ ///
+ /// @param[in] src_len
+ /// The number of bytes to attempt to write, and also the
+ /// number of bytes are currently available in \a src.
+ ///
+ /// @return
+ /// The number of bytes actually Written.
+ //------------------------------------------------------------------
+ size_t
+ Write (const void *src,
+ size_t src_len,
+ lldb::ConnectionStatus &status,
+ Error *error_ptr);
+
+ //------------------------------------------------------------------
+ /// Sets the connection that it to be used by this class.
+ ///
+ /// By making a communication class that uses different connections
+ /// it allows a single communication interface to negotiate and
+ /// change its connection without any interruption to the client.
+ /// It also allows the Communication class to be subclassed for
+ /// packet based communication.
+ ///
+ /// @param[in] connection
+ /// A connection that this class will own and destroy.
+ ///
+ /// @see
+ /// class Connection
+ //------------------------------------------------------------------
+ void
+ SetConnection (Connection *connection);
+
+ //------------------------------------------------------------------
+ /// Starts a read thread whose sole purpose it to read bytes from
+ /// the current connection. This function will call connection's
+ /// read function:
+ ///
+ /// size_t Connection::Read (void *, size_t);
+ ///
+ /// When bytes are read and cached, this function will call:
+ ///
+ /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast);
+ ///
+ /// Subclasses should override this function if they wish to override
+ /// the default action of caching the bytes and broadcasting a \b
+ /// eBroadcastBitReadThreadGotBytes event.
+ ///
+ /// @return
+ /// \b True if the read thread was successfully started, \b
+ /// false otherwise.
+ ///
+ /// @see size_t Connection::Read (void *, size_t);
+ /// @see void Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast);
+ //------------------------------------------------------------------
+ virtual bool
+ StartReadThread (Error *error_ptr = NULL);
+
+ //------------------------------------------------------------------
+ /// Stops the read thread by cancelling it.
+ ///
+ /// @return
+ /// \b True if the read thread was successfully canceled, \b
+ /// false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ StopReadThread (Error *error_ptr = NULL);
+
+ //------------------------------------------------------------------
+ /// Checks if there is a currently running read thread.
+ ///
+ /// @return
+ /// \b True if the read thread is running, \b false otherwise.
+ //------------------------------------------------------------------
+ bool
+ ReadThreadIsRunning ();
+
+ //------------------------------------------------------------------
+ /// The static read thread function. This function will call
+ /// the "DoRead" function continuously and wait for data to become
+ /// avaialble. When data is received it will append the available
+ /// data to the internal cache and broadcast a
+ /// \b eBroadcastBitReadThreadGotBytes event.
+ ///
+ /// @param[in] comm_ptr
+ /// A pointer to an instance of this class.
+ ///
+ /// @return
+ /// \b NULL.
+ ///
+ /// @see void Communication::ReadThreadGotBytes (const uint8_t *, size_t);
+ //------------------------------------------------------------------
+ static lldb::thread_result_t
+ ReadThread (lldb::thread_arg_t comm_ptr);
+
+ void
+ SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback,
+ void *callback_baton);
+
+ static const char *
+ ConnectionStatusAsCString (lldb::ConnectionStatus status);
+
+ bool
+ GetCloseOnEOF () const
+ {
+ return m_close_on_eof;
+ }
+
+ void
+ SetCloseOnEOF (bool b)
+ {
+ m_close_on_eof = b;
+ }
+
+ static ConstString &GetStaticBroadcasterClass ();
+
+ virtual ConstString &GetBroadcasterClass() const
+ {
+ return GetStaticBroadcasterClass();
+ }
+
+private:
+ //------------------------------------------------------------------
+ // For Communication only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (Communication);
+
+
+protected:
+ lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use by this communications class.
+ lldb::thread_t m_read_thread; ///< The read thread handle in case we need to cancel the thread.
+ bool m_read_thread_enabled;
+ std::string m_bytes; ///< A buffer to cache bytes read in the ReadThread function.
+ Mutex m_bytes_mutex; ///< A mutex to protect multi-threaded access to the cached bytes.
+ Mutex m_write_mutex; ///< Don't let multiple threads write at the same time...
+ ReadThreadBytesReceived m_callback;
+ void *m_callback_baton;
+ bool m_close_on_eof;
+
+ size_t
+ ReadFromConnection (void *dst,
+ size_t dst_len,
+ uint32_t timeout_usec,
+ lldb::ConnectionStatus &status,
+ Error *error_ptr);
+ //------------------------------------------------------------------
+ /// Append new bytes that get read from the read thread into the
+ /// internal object byte cache. This will cause a \b
+ /// eBroadcastBitReadThreadGotBytes event to be broadcast if \a
+ /// broadcast is true.
+ ///
+ /// Subclasses can override this function in order to inspect the
+ /// received data and check if a packet is available.
+ ///
+ /// Subclasses can also still call this function from the
+ /// overridden method to allow the caching to correctly happen and
+ /// suppress the broadcasting of the \a eBroadcastBitReadThreadGotBytes
+ /// event by setting \a broadcast to false.
+ ///
+ /// @param[in] src
+ /// A source buffer that must be at least \a src_len bytes
+ /// long.
+ ///
+ /// @param[in] src_len
+ /// The number of bytes to append to the cache.
+ //------------------------------------------------------------------
+ virtual void
+ AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast, lldb::ConnectionStatus status);
+
+ //------------------------------------------------------------------
+ /// Get any available bytes from our data cache. If this call
+ /// empties the data cache, the \b eBroadcastBitReadThreadGotBytes event
+ /// will be reset to signify no more bytes are available.
+ ///
+ /// @param[in] dst
+ /// A destination buffer that must be at least \a dst_len bytes
+ /// long.
+ ///
+ /// @param[in] dst_len
+ /// The number of bytes to attempt to read from the cache,
+ /// and also the max number of bytes that can be placed into
+ /// \a dst.
+ ///
+ /// @return
+ /// The number of bytes extracted from the data cache.
+ //------------------------------------------------------------------
+ size_t
+ GetCachedBytes (void *dst, size_t dst_len);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Communication_h_
OpenPOWER on IntegriCloud