Bug 879821 - NFC B2G IPC Implementation Using UnixSockets; r=qdot
authorSiddartha P <psiddh@gmail.com>
Mon, 17 Jun 2013 15:33:48 -0700
changeset 142530 80ebe45d4652bbe3b116dc71c1d59500902218ed
parent 142529 c55b4e2fa1bec283eef9364690a3b3c27b9b115d
child 142531 8b8ea8e11f7a87d15e9cfa214115292b86259411
push id3911
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 20:17:26 +0000
treeherdermozilla-aurora@7e26ca8db92b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs879821
milestone24.0a1
Bug 879821 - NFC B2G IPC Implementation Using UnixSockets; r=qdot
ipc/nfc/Makefile.in
ipc/nfc/Nfc.cpp
ipc/nfc/Nfc.h
ipc/nfc/moz.build
new file mode 100644
--- /dev/null
+++ b/ipc/nfc/Makefile.in
@@ -0,0 +1,22 @@
+# 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/.
+
+DEPTH = @DEPTH@
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+LIBRARY_NAME = moznfc_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+EXPORT_LIBRARY = 1
+
+EXPORTS_NAMESPACES = mozilla/ipc
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/ipc/nfc/Nfc.cpp
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et ft=cpp: */
+/* 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 <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#undef LOG
+#if defined(MOZ_WIDGET_GONK)
+#include <android/log.h>
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
+#else
+#define LOG(args...)  printf(args);
+#endif
+
+#include "jsfriendapi.h"
+#include "nsThreadUtils.h" // For NS_IsMainThread.
+#include "Nfc.h"
+
+USING_WORKERS_NAMESPACE
+using namespace mozilla::ipc;
+
+namespace {
+
+const char* NFC_SOCKET_NAME = "/dev/socket/nfcd";
+
+// Network port to connect to for adb forwarded sockets when doing
+// desktop development.
+const uint32_t NFCD_TEST_PORT = 6400;
+
+class DispatchNfcEvent : public WorkerTask
+{
+public:
+    DispatchNfcEvent(UnixSocketRawData* aMessage)
+      : mMessage(aMessage)
+    { }
+
+    virtual bool RunTask(JSContext *aCx);
+
+private:
+    nsAutoPtr<UnixSocketRawData> mMessage;
+};
+
+bool
+DispatchNfcEvent::RunTask(JSContext *aCx)
+{
+    MOZ_ASSERT(NS_IsMainThread(), "DispatchNfcEvent on main thread");
+    MOZ_ASSERT(aCx);
+
+    JSObject *obj = JS_GetGlobalForScopeChain(aCx);
+    JSObject *array = JS_NewUint8Array(aCx, mMessage->mSize);
+    if (!array) {
+        return false;
+    }
+    memcpy(JS_GetArrayBufferViewData(array), mMessage->mData, mMessage->mSize);
+    jsval argv[] = { OBJECT_TO_JSVAL(array) };
+    return JS_CallFunctionName(aCx, obj, "onNfcMessage", NS_ARRAY_LENGTH(argv),
+                               argv, argv);
+}
+
+class NfcConnector : public mozilla::ipc::UnixSocketConnector
+{
+public:
+    NfcConnector() {}
+    virtual ~NfcConnector()
+    {}
+
+    virtual int Create();
+    virtual bool CreateAddr(bool aIsServer,
+                            socklen_t& aAddrSize,
+                            sockaddr_any& aAddr,
+                            const char* aAddress);
+    virtual bool SetUp(int aFd);
+    virtual void GetSocketAddr(const sockaddr_any& aAddr,
+                               nsAString& aAddrStr);
+};
+
+int
+NfcConnector::Create()
+{
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    int fd = -1;
+
+#if defined(MOZ_WIDGET_GONK)
+    fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+#else
+    // If we can't hit a local loopback, fail later in connect.
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+#endif
+
+    if (fd < 0) {
+        NS_WARNING("Could not open Nfc socket!");
+        return -1;
+    }
+
+    if (!SetUp(fd)) {
+        NS_WARNING("Could not set up socket!");
+    }
+    return fd;
+}
+
+bool
+NfcConnector::CreateAddr(bool aIsServer,
+                         socklen_t& aAddrSize,
+                         sockaddr_any& aAddr,
+                         const char* aAddress)
+{
+    // We never open nfc socket as server.
+    MOZ_ASSERT(!aIsServer);
+    uint32_t af;
+#if defined(MOZ_WIDGET_GONK)
+    af = AF_LOCAL;
+#else
+    af = AF_INET;
+#endif
+    switch (af) {
+    case AF_LOCAL:
+        aAddr.un.sun_family = af;
+        if(strlen(aAddress) > sizeof(aAddr.un.sun_path)) {
+            NS_WARNING("Address too long for socket struct!");
+            return false;
+        }
+        strcpy((char*)&aAddr.un.sun_path, aAddress);
+        aAddrSize = strlen(aAddress) + offsetof(struct sockaddr_un, sun_path) + 1;
+        break;
+    case AF_INET:
+        aAddr.in.sin_family = af;
+        aAddr.in.sin_port = htons(NFCD_TEST_PORT);
+        aAddr.in.sin_addr.s_addr = htons(INADDR_LOOPBACK);
+        aAddrSize = sizeof(sockaddr_in);
+        break;
+    default:
+        NS_WARNING("Socket type not handled by connector!");
+        return false;
+    }
+    return true;
+
+}
+
+bool
+NfcConnector::SetUp(int aFd)
+{
+    // Nothing to do here.
+    return true;
+}
+
+void
+NfcConnector::GetSocketAddr(const sockaddr_any& aAddr,
+                            nsAString& aAddrStr)
+{
+    MOZ_NOT_REACHED("This should never be called!");
+}
+
+} // anonymous namespace
+
+
+namespace mozilla {
+namespace ipc {
+
+NfcConsumer::NfcConsumer(WorkerCrossThreadDispatcher* aDispatcher)
+    : mDispatcher(aDispatcher)
+    , mShutdown(false)
+{
+    ConnectSocket(new NfcConnector(), NFC_SOCKET_NAME);
+}
+
+void
+NfcConsumer::Shutdown()
+{
+    mShutdown = true;
+    CloseSocket();
+}
+
+void
+NfcConsumer::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
+{
+    MOZ_ASSERT(NS_IsMainThread());
+#ifdef DEBUG
+    LOG("ReceiveSocketData\n");
+#endif
+    nsRefPtr<DispatchNfcEvent> dre(new DispatchNfcEvent(aMessage.forget()));
+    mDispatcher->PostTask(dre);
+}
+
+void
+NfcConsumer::OnConnectSuccess()
+{
+    // Nothing to do here.
+    LOG("Socket open for Nfc\n");
+}
+
+void
+NfcConsumer::OnConnectError()
+{
+#ifdef DEBUG
+    LOG("%s\n", __FUNCTION__);
+#endif
+    CloseSocket();
+}
+
+void
+NfcConsumer::OnDisconnect()
+{
+#ifdef DEBUG
+    LOG("%s\n", __FUNCTION__);
+#endif
+    if (!mShutdown) {
+        ConnectSocket(new NfcConnector(), NFC_SOCKET_NAME, 1000);
+    }
+}
+
+} // namespace ipc
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/nfc/Nfc.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp: */
+/* 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_Nfc_h
+#define mozilla_ipc_Nfc_h 1
+
+#include <mozilla/dom/workers/Workers.h>
+#include <mozilla/ipc/UnixSocket.h>
+
+namespace mozilla {
+namespace ipc {
+
+class NfcConsumer : public mozilla::ipc::UnixSocketConsumer
+{
+public:
+    NfcConsumer(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
+    virtual ~NfcConsumer() { }
+    void Shutdown();
+private:
+    virtual void ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage);
+
+    virtual void OnConnectSuccess();
+    virtual void OnConnectError();
+    virtual void OnDisconnect();
+
+private:
+    nsRefPtr<mozilla::dom::workers::WorkerCrossThreadDispatcher> mDispatcher;
+    bool mShutdown;
+};
+
+} // namespace ipc
+} // namepsace mozilla
+
+#endif // mozilla_ipc_Nfc_h
new file mode 100644
--- /dev/null
+++ b/ipc/nfc/moz.build
@@ -0,0 +1,13 @@
+# vim: set filetype=python:
+# 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/.
+
+if CONFIG['MOZ_B2G_NFC']:
+    MODULE = 'ipc'
+    EXPORTS.mozilla.ipc += [
+        'Nfc.h',
+    ]
+    CPP_SOURCES += [
+        'Nfc.cpp',
+    ]