mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 07:05:24 +00:00
3ac31d4e70
MozReview-Commit-ID: JHVQ6BFvS1Z --HG-- extra : rebase_source : 716d827e989d7a9e94478612c73f54f4bfe5aca5
586 lines
12 KiB
C++
586 lines
12 KiB
C++
/* -*- 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
|