gecko/ipc/unixsocket/DataSocket.cpp
2015-07-21 08:06:29 +02:00

137 lines
3.0 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/.
*/
#include "DataSocket.h"
#ifdef MOZ_TASK_TRACER
#include "GeckoTaskTracer.h"
#endif
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
#ifdef MOZ_TASK_TRACER
using namespace mozilla::tasktracer;
#endif
namespace mozilla {
namespace ipc {
//
// DataSocketIO
//
DataSocketIO::~DataSocketIO()
{
MOZ_COUNT_DTOR_INHERITED(DataSocketIO, SocketIOBase);
}
void
DataSocketIO::EnqueueData(UnixSocketIOBuffer* aBuffer)
{
if (!aBuffer->GetSize()) {
delete aBuffer; // delete empty data immediately
return;
}
mOutgoingQ.AppendElement(aBuffer);
}
bool
DataSocketIO::HasPendingData() const
{
return !mOutgoingQ.IsEmpty();
}
ssize_t
DataSocketIO::ReceiveData(int aFd)
{
MOZ_ASSERT(aFd >= 0);
UnixSocketIOBuffer* incoming;
nsresult rv = QueryReceiveBuffer(&incoming);
if (NS_FAILED(rv)) {
/* an error occured */
GetConsumerThread()->PostTask(FROM_HERE,
new SocketRequestClosingTask(this));
return -1;
}
ssize_t res = incoming->Receive(aFd);
if (res < 0) {
/* an I/O error occured */
DiscardBuffer();
GetConsumerThread()->PostTask(FROM_HERE,
new SocketRequestClosingTask(this));
return -1;
} else if (!res) {
/* EOF or peer shut down sending */
DiscardBuffer();
GetConsumerThread()->PostTask(FROM_HERE,
new SocketRequestClosingTask(this));
return 0;
}
#ifdef MOZ_TASK_TRACER
/* Make unix socket creation events to be the source events of TaskTracer,
* and originate the rest correlation tasks from here.
*/
AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket);
#endif
ConsumeBuffer();
return res;
}
nsresult
DataSocketIO::SendPendingData(int aFd)
{
MOZ_ASSERT(aFd >= 0);
while (HasPendingData()) {
UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0);
ssize_t res = outgoing->Send(aFd);
if (res < 0) {
/* an I/O error occured */
GetConsumerThread()->PostTask(FROM_HERE,
new SocketRequestClosingTask(this));
return NS_ERROR_FAILURE;
} else if (!res && outgoing->GetSize()) {
/* I/O is currently blocked; try again later */
return NS_OK;
}
if (!outgoing->GetSize()) {
mOutgoingQ.RemoveElementAt(0);
delete outgoing;
}
}
return NS_OK;
}
DataSocketIO::DataSocketIO(MessageLoop* aConsumerLoop)
: SocketIOBase(aConsumerLoop)
{
MOZ_COUNT_CTOR_INHERITED(DataSocketIO, SocketIOBase);
}
//
// DataSocket
//
DataSocket::DataSocket()
{
MOZ_COUNT_CTOR_INHERITED(DataSocket, SocketBase);
}
DataSocket::~DataSocket()
{
MOZ_COUNT_DTOR_INHERITED(DataSocket, SocketBase);
}
}
}