Bug 879821 - NFC B2G IPC Implementation Using UnixSockets; r=qdot
authorSiddartha P <psiddh@gmail.com>
Mon, 17 Jun 2013 15:33:48 -0700
changeset 146903 80ebe45d4652bbe3b116dc71c1d59500902218ed
parent 146902 c55b4e2fa1bec283eef9364690a3b3c27b9b115d
child 146904 8b8ea8e11f7a87d15e9cfa214115292b86259411
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs879821
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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',
+    ]