summaryrefslogtreecommitdiff
path: root/ipc/unixsocket/SocketBase.h
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/unixsocket/SocketBase.h')
-rw-r--r--ipc/unixsocket/SocketBase.h585
1 files changed, 585 insertions, 0 deletions
diff --git a/ipc/unixsocket/SocketBase.h b/ipc/unixsocket/SocketBase.h
new file mode 100644
index 0000000000..191567fdb9
--- /dev/null
+++ b/ipc/unixsocket/SocketBase.h
@@ -0,0 +1,585 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef mozilla_ipc_SocketBase_h
+#define mozilla_ipc_SocketBase_h
+
+#include "base/message_loop.h"
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+namespace ipc {
+
+//
+// UnixSocketBuffer
+//
+
+/**
+ * |UnixSocketBuffer| implements a FIFO buffer that stores raw socket
+ * data, either for sending on a socket or received from a socket.
+ */
+class UnixSocketBuffer
+{
+public:
+ virtual ~UnixSocketBuffer();
+
+ const uint8_t* GetData() const
+ {
+ return mData + mOffset;
+ }
+
+ size_t GetSize() const
+ {
+ return mSize - mOffset;
+ }
+
+ const uint8_t* Consume(size_t aLen);
+
+ nsresult Read(void* aValue, size_t aLen);
+
+ nsresult Read(int8_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(uint8_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(int16_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(uint16_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(int32_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(uint32_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(int64_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(uint64_t& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(float& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ nsresult Read(double& aValue)
+ {
+ return Read(&aValue, sizeof(aValue));
+ }
+
+ uint8_t* Append(size_t aLen);
+
+ nsresult Write(const void* aValue, size_t aLen);
+
+ nsresult Write(int8_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(uint8_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(int16_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(uint16_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(int32_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(uint32_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(int64_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(uint64_t aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(float aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+ nsresult Write(double aValue)
+ {
+ return Write(&aValue, sizeof(aValue));
+ }
+
+protected:
+ UnixSocketBuffer();
+
+ /**
+ * Sets the raw memory. The caller is responsible for freeing
+ * this memory.
+ *
+ * @param aData A pointer to the buffer's raw memory.
+ * @param aOffset The start of valid bytes in |aData|.
+ * @param aSize The number of valid bytes in |aData|.
+ * @param aAvailableSpace The number of bytes in |aData|.
+ */
+ void ResetBuffer(uint8_t* aData,
+ size_t aOffset, size_t aSize, size_t aAvailableSpace)
+ {
+ MOZ_ASSERT(aData || !aAvailableSpace);
+ MOZ_ASSERT((aOffset + aSize) <= aAvailableSpace);
+
+ mOffset = aOffset;
+ mSize = aSize;
+ mAvailableSpace = aAvailableSpace;
+ mData = aData;
+ }
+
+ /**
+ * Retrieves the memory buffer.
+ *
+ * @return A pointer to the buffer's raw memory.
+ */
+ uint8_t* GetBuffer()
+ {
+ return mData;
+ }
+
+ size_t GetLeadingSpace() const
+ {
+ return mOffset;
+ }
+
+ size_t GetTrailingSpace() const
+ {
+ return mAvailableSpace - mSize;
+ }
+
+ size_t GetAvailableSpace() const
+ {
+ return mAvailableSpace;
+ }
+
+ void* GetTrailingBytes()
+ {
+ return mData + mSize;
+ }
+
+ uint8_t* GetData(size_t aOffset)
+ {
+ MOZ_ASSERT(aOffset <= mSize);
+
+ return mData + aOffset;
+ }
+
+ void SetRange(size_t aOffset, size_t aSize)
+ {
+ MOZ_ASSERT((aOffset + aSize) <= mAvailableSpace);
+
+ mOffset = aOffset;
+ mSize = mOffset + aSize;
+ }
+
+ void CleanupLeadingSpace();
+
+private:
+ size_t mSize;
+ size_t mOffset;
+ size_t mAvailableSpace;
+ uint8_t* mData;
+};
+
+//
+// UnixSocketIOBuffer
+//
+
+/**
+ * |UnixSocketIOBuffer| is a |UnixSocketBuffer| that supports being
+ * received on a socket or being send on a socket. Network protocols
+ * might differ in their exact usage of Unix socket functions and
+ * |UnixSocketIOBuffer| provides a protocol-neutral interface.
+ */
+class UnixSocketIOBuffer : public UnixSocketBuffer
+{
+public:
+ UnixSocketIOBuffer();
+ virtual ~UnixSocketIOBuffer();
+
+ /**
+ * Receives data from aFd at the end of the buffer. The returned value
+ * is the number of newly received bytes, or 0 if the peer shut down
+ * its connection, or a negative value on errors.
+ */
+ virtual ssize_t Receive(int aFd) = 0;
+
+ /**
+ * Sends data to aFd from the beginning of the buffer. The returned value
+ * is the number of bytes written, or a negative value on error.
+ */
+ virtual ssize_t Send(int aFd) = 0;
+};
+
+//
+// UnixSocketRawData
+//
+
+class UnixSocketRawData final : public UnixSocketIOBuffer
+{
+public:
+ /**
+ * This constructor copies aData of aSize bytes length into the
+ * new instance of |UnixSocketRawData|.
+ *
+ * @param aData The buffer to copy.
+ * @param aSize The number of bytes in |aData|.
+ */
+ UnixSocketRawData(const void* aData, size_t aSize);
+
+ /**
+ * This constructor takes ownership of the data in aData. The
+ * data is assumed to be aSize bytes in length.
+ *
+ * @param aData The buffer to take ownership of.
+ * @param aSize The number of bytes in |aData|.
+ */
+ UnixSocketRawData(UniquePtr<uint8_t[]> aData, size_t aSize);
+
+ /**
+ * This constructor reserves aSize bytes of space. Currently
+ * it's only possible to fill this buffer by calling |Receive|.
+ *
+ * @param aSize The number of bytes to allocate.
+ */
+ UnixSocketRawData(size_t aSize);
+
+ /**
+ * The destructor releases the buffer's raw memory.
+ */
+ ~UnixSocketRawData();
+
+ /**
+ * Receives data from aFd at the end of the buffer. The returned value
+ * is the number of newly received bytes, or 0 if the peer shut down
+ * its connection, or a negative value on errors.
+ */
+ ssize_t Receive(int aFd) override;
+
+ /**
+ * Sends data to aFd from the beginning of the buffer. The returned value
+ * is the number of bytes written, or a negative value on error.
+ */
+ ssize_t Send(int aFd) override;
+};
+
+enum SocketConnectionStatus {
+ SOCKET_DISCONNECTED = 0,
+ SOCKET_LISTENING = 1,
+ SOCKET_CONNECTING = 2,
+ SOCKET_CONNECTED = 3
+};
+
+//
+// SocketBase
+//
+
+class SocketBase
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketBase)
+
+ SocketConnectionStatus GetConnectionStatus() const;
+
+ int GetSuggestedConnectDelayMs() const;
+
+ /**
+ * Queues the internal representation of socket for deletion. Can be called
+ * from consumer thread.
+ */
+ virtual void Close() = 0;
+
+ /**
+ * Callback for socket connect/accept success. Called after connect/accept has
+ * finished. Will be run on consumer thread before any reads take place.
+ */
+ virtual void OnConnectSuccess() = 0;
+
+ /**
+ * Callback for socket connect/accept error. Will be run on consumer thread.
+ */
+ virtual void OnConnectError() = 0;
+
+ /**
+ * Callback for socket disconnect. Will be run on consumer thread.
+ */
+ virtual void OnDisconnect() = 0;
+
+ /**
+ * Called by implementation to notify consumer of success.
+ */
+ void NotifySuccess();
+
+ /**
+ * Called by implementation to notify consumer of error.
+ */
+ void NotifyError();
+
+ /**
+ * Called by implementation to notify consumer of disconnect.
+ */
+ void NotifyDisconnect();
+
+protected:
+ SocketBase();
+ virtual ~SocketBase();
+
+ void SetConnectionStatus(SocketConnectionStatus aConnectionStatus);
+
+private:
+ uint32_t CalculateConnectDelayMs() const;
+
+ SocketConnectionStatus mConnectionStatus;
+ PRIntervalTime mConnectTimestamp;
+ uint32_t mConnectDelayMs;
+};
+
+//
+// SocketIOBase
+//
+
+/**
+ * |SocketIOBase| is a base class for Socket I/O classes that
+ * perform operations on the I/O thread.
+ */
+class SocketIOBase
+{
+public:
+ virtual ~SocketIOBase();
+
+ /**
+ * Implemented by socket I/O classes to return the current instance of
+ * |SocketBase|.
+ *
+ * @return The current instance of |SocketBase|
+ */
+ virtual SocketBase* GetSocketBase() = 0;
+
+ /**
+ * Implemented by socket I/O classes to signal that the socket I/O class has
+ * been shut down.
+ *
+ * @return True if the socket I/O class has been shut down, false otherwise.
+ */
+ virtual bool IsShutdownOnIOThread() const = 0;
+
+ /**
+ * Implemented by socket I/O classes to signal that socket class has
+ * been shut down.
+ *
+ * @return True if the socket class has been shut down, false otherwise.
+ */
+ virtual bool IsShutdownOnConsumerThread() const = 0;
+
+ /**
+ * Signals to the socket I/O classes that it has been shut down.
+ */
+ virtual void ShutdownOnIOThread() = 0;
+
+ /**
+ * Signals to the socket I/O classes that the socket class has been
+ * shut down.
+ */
+ virtual void ShutdownOnConsumerThread() = 0;
+
+ /**
+ * Returns the consumer thread.
+ *
+ * @return A pointer to the consumer thread.
+ */
+ MessageLoop* GetConsumerThread() const;
+
+ /**
+ * @return True if the current thread is the consumer thread, or false
+ * otherwise.
+ */
+ bool IsConsumerThread() const;
+
+protected:
+ SocketIOBase(MessageLoop* aConsumerLoop);
+
+private:
+ MessageLoop* mConsumerLoop;
+};
+
+//
+// Socket tasks
+//
+
+/* |SocketTask| is a task for sending a message from
+ * the I/O thread to the consumer thread.
+ */
+template <typename T>
+class SocketTask : public CancelableRunnable
+{
+public:
+ virtual ~SocketTask()
+ { }
+
+ T* GetIO() const
+ {
+ return mIO;
+ }
+
+protected:
+ SocketTask(T* aIO)
+ : mIO(aIO)
+ {
+ MOZ_ASSERT(aIO);
+ }
+
+private:
+ T* mIO;
+};
+
+/**
+ * |SocketEventTask| reports the connection state on the
+ * I/O thread back to the consumer thread.
+ */
+class SocketEventTask final : public SocketTask<SocketIOBase>
+{
+public:
+ enum SocketEvent {
+ CONNECT_SUCCESS,
+ CONNECT_ERROR,
+ DISCONNECT
+ };
+
+ SocketEventTask(SocketIOBase* aIO, SocketEvent aEvent);
+ ~SocketEventTask();
+
+ NS_IMETHOD Run() override;
+
+private:
+ SocketEvent mEvent;
+};
+
+/**
+ * |SocketRequestClosingTask| closes an instance of |SocketBase|
+ * on the consumer thread.
+ */
+class SocketRequestClosingTask final : public SocketTask<SocketIOBase>
+{
+public:
+ SocketRequestClosingTask(SocketIOBase* aIO);
+ ~SocketRequestClosingTask();
+
+ NS_IMETHOD Run() override;
+};
+
+/**
+ * |SocketDeleteInstanceTask| deletes an object on the consumer thread.
+ */
+class SocketDeleteInstanceTask final : public Runnable
+{
+public:
+ SocketDeleteInstanceTask(SocketIOBase* aIO);
+ ~SocketDeleteInstanceTask();
+
+ NS_IMETHOD Run() override;
+
+private:
+ UniquePtr<SocketIOBase> mIO;
+};
+
+//
+// Socket I/O tasks
+//
+
+/* |SocketIOTask| holds a reference to a Socket I/O object. It's
+ * supposed to run on the I/O thread.
+ */
+template<typename Tio>
+class SocketIOTask : public CancelableRunnable
+{
+public:
+ virtual ~SocketIOTask()
+ { }
+
+ Tio* GetIO() const
+ {
+ return mIO;
+ }
+
+ nsresult Cancel() override
+ {
+ mIO = nullptr;
+ return NS_OK;
+ }
+
+ bool IsCanceled() const
+ {
+ return !mIO;
+ }
+
+protected:
+ SocketIOTask(Tio* aIO)
+ : mIO(aIO)
+ {
+ MOZ_ASSERT(mIO);
+ }
+
+private:
+ Tio* mIO;
+};
+
+/**
+ * |SocketIOShutdownTask| signals shutdown to the socket I/O class on
+ * the I/O thread and sends it to the consumer thread for destruction.
+ */
+class SocketIOShutdownTask final : public SocketIOTask<SocketIOBase>
+{
+public:
+ SocketIOShutdownTask(SocketIOBase* aIO);
+ ~SocketIOShutdownTask();
+
+ NS_IMETHOD Run() override;
+};
+
+}
+}
+
+#endif