Bug 1083092: Add |mozilla::ipc::UnixSocketIOBuffer|, r=shawnjohnjr

The class |UnixSocketIOBuffer| maintains memory buffers for socket I/O
operations. The actual I/O is still implemented by subclasses, such as
|UnixSocketRawData|.
This commit is contained in:
Thomas Zimmermann 2014-10-21 10:52:12 +02:00
parent 51eba88842
commit 7c3cf9bdb8
2 changed files with 225 additions and 57 deletions

View File

@ -15,10 +15,10 @@ namespace mozilla {
namespace ipc {
//
// UnixSocketRawData
// UnixSocketIOBuffer
//
UnixSocketRawData::UnixSocketRawData(const void* aData, size_t aSize)
UnixSocketIOBuffer::UnixSocketIOBuffer(const void* aData, size_t aSize)
: mSize(aSize)
, mOffset(0)
, mAvailableSpace(aSize)
@ -29,14 +29,90 @@ UnixSocketRawData::UnixSocketRawData(const void* aData, size_t aSize)
memcpy(mData, aData, mSize);
}
UnixSocketRawData::UnixSocketRawData(size_t aSize)
UnixSocketIOBuffer::UnixSocketIOBuffer(size_t aAvailableSpace)
: mSize(0)
, mOffset(0)
, mAvailableSpace(aSize)
, mAvailableSpace(aAvailableSpace)
{
mData = new uint8_t[mAvailableSpace];
}
UnixSocketIOBuffer::~UnixSocketIOBuffer()
{ }
const uint8_t*
UnixSocketIOBuffer::Consume(size_t aLen)
{
if (NS_WARN_IF(GetSize() < aLen)) {
return nullptr;
}
uint8_t* data = mData + mOffset;
mOffset += aLen;
return data;
}
nsresult
UnixSocketIOBuffer::Read(void* aValue, size_t aLen)
{
const uint8_t* data = Consume(aLen);
if (!data) {
return NS_ERROR_OUT_OF_MEMORY;
}
memcpy(aValue, data, aLen);
return NS_OK;
}
uint8_t*
UnixSocketIOBuffer::Append(size_t aLen)
{
if (((mAvailableSpace - mSize) < aLen)) {
size_t availableSpace = mAvailableSpace + std::max(mAvailableSpace, aLen);
uint8_t* data = new uint8_t[availableSpace];
memcpy(data, mData, mSize);
mData = data;
mAvailableSpace = availableSpace;
}
uint8_t* data = mData + mSize;
mSize += aLen;
return data;
}
nsresult
UnixSocketIOBuffer::Write(const void* aValue, size_t aLen)
{
uint8_t* data = Append(aLen);
if (!data) {
return NS_ERROR_OUT_OF_MEMORY;
}
memcpy(data, aValue, aLen);
return NS_OK;
}
void
UnixSocketIOBuffer::CleanupLeadingSpace()
{
if (GetLeadingSpace()) {
if (GetSize() <= GetLeadingSpace()) {
memcpy(mData, GetData(), GetSize());
} else {
memmove(mData, GetData(), GetSize());
}
mOffset = 0;
}
}
//
// UnixSocketRawData
//
UnixSocketRawData::UnixSocketRawData(const void* aData, size_t aSize)
: UnixSocketIOBuffer(aData, aSize)
{ }
UnixSocketRawData::UnixSocketRawData(size_t aSize)
: UnixSocketIOBuffer(aSize)
{ }
ssize_t
UnixSocketRawData::Receive(int aFd)
{
@ -45,12 +121,7 @@ UnixSocketRawData::Receive(int aFd)
return -1; /* buffer is full */
}
/* free up space at the end of data buffer */
if (GetSize() <= GetLeadingSpace()) {
memcpy(mData, GetData(), GetSize());
} else {
memmove(mData, GetData(), GetSize());
}
mOffset = 0;
CleanupLeadingSpace();
}
ssize_t res =
@ -64,7 +135,7 @@ UnixSocketRawData::Receive(int aFd)
return 0;
}
mSize += res;
Append(res); /* mark read data as 'valid' */
return res;
}

View File

@ -22,11 +22,153 @@ using namespace mozilla::tasktracer;
namespace mozilla {
namespace ipc {
//
// UnixSocketIOBuffer
//
class UnixSocketIOBuffer
{
public:
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));
}
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));
}
protected:
/* This constructor copies aData of aSize bytes length into the
* new instance of |UnixSocketIOBuffer|.
*/
UnixSocketIOBuffer(const void* aData, size_t aSize);
/* This constructor reserves aAvailableSpace bytes of space.
*/
UnixSocketIOBuffer(size_t aAvailableSpace);
~UnixSocketIOBuffer();
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;
nsAutoArrayPtr<uint8_t> mData;
};
//
// UnixSocketRawData
//
class UnixSocketRawData
class UnixSocketRawData MOZ_FINAL : public UnixSocketIOBuffer
{
public:
/* This constructor copies aData of aSize bytes length into the
@ -51,51 +193,6 @@ public:
* is the number of bytes written, or a negative value on error.
*/
ssize_t Send(int aFd);
const uint8_t* GetData() const
{
return mData + mOffset;
}
size_t GetSize() const
{
return mSize;
}
void Consume(size_t aSize)
{
MOZ_ASSERT(aSize <= mSize);
mSize -= aSize;
mOffset += aSize;
}
protected:
size_t GetLeadingSpace() const
{
return mOffset;
}
size_t GetTrailingSpace() const
{
return mAvailableSpace - (mOffset + mSize);
}
size_t GetAvailableSpace() const
{
return mAvailableSpace;
}
void* GetTrailingBytes()
{
return mData + mOffset + mSize;
}
private:
size_t mSize;
size_t mOffset;
size_t mAvailableSpace;
nsAutoArrayPtr<uint8_t> mData;
};
enum SocketConnectionStatus {