summaryrefslogtreecommitdiffstats
path: root/ipc/hal/DaemonSocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/hal/DaemonSocket.cpp')
-rw-r--r--ipc/hal/DaemonSocket.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/ipc/hal/DaemonSocket.cpp b/ipc/hal/DaemonSocket.cpp
new file mode 100644
index 000000000..94c36b955
--- /dev/null
+++ b/ipc/hal/DaemonSocket.cpp
@@ -0,0 +1,263 @@
+/* -*- 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 "DaemonSocket.h"
+#include "mozilla/ipc/DaemonSocketConsumer.h"
+#include "mozilla/ipc/DaemonSocketPDU.h"
+#include "mozilla/UniquePtr.h"
+#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, MOZ_COUNT_DTOR
+
+#ifdef CHROMIUM_LOG
+#undef CHROMIUM_LOG
+#endif
+
+#if defined(MOZ_WIDGET_GONK)
+#include <android/log.h>
+#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "I/O", args);
+#else
+#include <stdio.h>
+#define IODEBUG true
+#define CHROMIUM_LOG(args...) if (IODEBUG) printf(args);
+#endif
+
+namespace mozilla {
+namespace ipc {
+
+//
+// DaemonSocketIO
+//
+
+class DaemonSocketIO final : public ConnectionOrientedSocketIO
+{
+public:
+ DaemonSocketIO(MessageLoop* aConsumerLoop,
+ MessageLoop* aIOLoop,
+ int aFd, ConnectionStatus aConnectionStatus,
+ UnixSocketConnector* aConnector,
+ DaemonSocket* aConnection,
+ DaemonSocketIOConsumer* aConsumer);
+
+ ~DaemonSocketIO();
+
+ // Methods for |DataSocketIO|
+ //
+
+ nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override;
+ void ConsumeBuffer() override;
+ void DiscardBuffer() override;
+
+ // Methods for |SocketIOBase|
+ //
+
+ SocketBase* GetSocketBase() override;
+
+ bool IsShutdownOnConsumerThread() const override;
+ bool IsShutdownOnIOThread() const override;
+
+ void ShutdownOnConsumerThread() override;
+ void ShutdownOnIOThread() override;
+
+private:
+ DaemonSocket* mConnection;
+ DaemonSocketIOConsumer* mConsumer;
+ UniquePtr<DaemonSocketPDU> mPDU;
+ bool mShuttingDownOnIOThread;
+};
+
+DaemonSocketIO::DaemonSocketIO(
+ MessageLoop* aConsumerLoop,
+ MessageLoop* aIOLoop,
+ int aFd,
+ ConnectionStatus aConnectionStatus,
+ UnixSocketConnector* aConnector,
+ DaemonSocket* aConnection,
+ DaemonSocketIOConsumer* aConsumer)
+ : ConnectionOrientedSocketIO(aConsumerLoop,
+ aIOLoop,
+ aFd,
+ aConnectionStatus,
+ aConnector)
+ , mConnection(aConnection)
+ , mConsumer(aConsumer)
+ , mShuttingDownOnIOThread(false)
+{
+ MOZ_ASSERT(mConnection);
+ MOZ_ASSERT(mConsumer);
+
+ MOZ_COUNT_CTOR_INHERITED(DaemonSocketIO, ConnectionOrientedSocketIO);
+}
+
+DaemonSocketIO::~DaemonSocketIO()
+{
+ MOZ_COUNT_DTOR_INHERITED(DaemonSocketIO, ConnectionOrientedSocketIO);
+}
+
+// |DataSocketIO|
+
+nsresult
+DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
+{
+ MOZ_ASSERT(aBuffer);
+
+ if (!mPDU) {
+ /* There's only one PDU for receiving. We reuse it every time. */
+ mPDU = MakeUnique<DaemonSocketPDU>(DaemonSocketPDU::PDU_MAX_PAYLOAD_LENGTH);
+ }
+ *aBuffer = mPDU.get();
+
+ return NS_OK;
+}
+
+void
+DaemonSocketIO::ConsumeBuffer()
+{
+ MOZ_ASSERT(mConsumer);
+
+ mConsumer->Handle(*mPDU);
+}
+
+void
+DaemonSocketIO::DiscardBuffer()
+{
+ // Nothing to do.
+}
+
+// |SocketIOBase|
+
+SocketBase*
+DaemonSocketIO::GetSocketBase()
+{
+ return mConnection;
+}
+
+bool
+DaemonSocketIO::IsShutdownOnConsumerThread() const
+{
+ MOZ_ASSERT(IsConsumerThread());
+
+ return mConnection == nullptr;
+}
+
+bool
+DaemonSocketIO::IsShutdownOnIOThread() const
+{
+ return mShuttingDownOnIOThread;
+}
+
+void
+DaemonSocketIO::ShutdownOnConsumerThread()
+{
+ MOZ_ASSERT(IsConsumerThread());
+ MOZ_ASSERT(!IsShutdownOnConsumerThread());
+
+ mConnection = nullptr;
+}
+
+void
+DaemonSocketIO::ShutdownOnIOThread()
+{
+ MOZ_ASSERT(!IsConsumerThread());
+ MOZ_ASSERT(!mShuttingDownOnIOThread);
+
+ Close(); // will also remove fd from I/O loop
+ mShuttingDownOnIOThread = true;
+}
+
+//
+// DaemonSocket
+//
+
+DaemonSocket::DaemonSocket(
+ DaemonSocketIOConsumer* aIOConsumer,
+ DaemonSocketConsumer* aConsumer,
+ int aIndex)
+ : mIO(nullptr)
+ , mIOConsumer(aIOConsumer)
+ , mConsumer(aConsumer)
+ , mIndex(aIndex)
+{
+ MOZ_ASSERT(mConsumer);
+
+ MOZ_COUNT_CTOR_INHERITED(DaemonSocket, ConnectionOrientedSocket);
+}
+
+DaemonSocket::~DaemonSocket()
+{
+ MOZ_COUNT_DTOR_INHERITED(DaemonSocket, ConnectionOrientedSocket);
+}
+
+// |ConnectionOrientedSocket|
+
+nsresult
+DaemonSocket::PrepareAccept(UnixSocketConnector* aConnector,
+ MessageLoop* aConsumerLoop,
+ MessageLoop* aIOLoop,
+ ConnectionOrientedSocketIO*& aIO)
+{
+ MOZ_ASSERT(!mIO);
+
+ SetConnectionStatus(SOCKET_CONNECTING);
+
+ mIO = new DaemonSocketIO(
+ aConsumerLoop, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
+ aConnector, this, mIOConsumer);
+ aIO = mIO;
+
+ return NS_OK;
+}
+
+// |DataSocket|
+
+void
+DaemonSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
+{
+ MOZ_ASSERT(mIO);
+ MOZ_ASSERT(mIO->IsConsumerThread());
+
+ mIO->GetIOLoop()->PostTask(
+ MakeAndAddRef<SocketIOSendTask<DaemonSocketIO, UnixSocketIOBuffer>>(
+ mIO, aBuffer));
+}
+
+// |SocketBase|
+
+void
+DaemonSocket::Close()
+{
+ if (!mIO) {
+ CHROMIUM_LOG("HAL daemon already disconnected!");
+ return;
+ }
+
+ MOZ_ASSERT(mIO->IsConsumerThread());
+
+ mIO->ShutdownOnConsumerThread();
+ mIO->GetIOLoop()->PostTask(MakeAndAddRef<SocketIOShutdownTask>(mIO));
+ mIO = nullptr;
+
+ NotifyDisconnect();
+}
+
+void
+DaemonSocket::OnConnectSuccess()
+{
+ mConsumer->OnConnectSuccess(mIndex);
+}
+
+void
+DaemonSocket::OnConnectError()
+{
+ mConsumer->OnConnectError(mIndex);
+}
+
+void
+DaemonSocket::OnDisconnect()
+{
+ mConsumer->OnDisconnect(mIndex);
+}
+
+}
+}