Bug 814579: connect client socket by id. r=qDot
☠☠ backed out by 8eeb4f842941 ☠ ☠
authorVicamo Yang <vyang@mozilla.com>
Sat, 02 Feb 2013 13:06:27 +0800
changeset 131315 9a7369b9bc9dde50952c43f74917ec0f59c0d7cb
parent 131314 14c50f120fe9efc5772c336434ef915100b70c43
child 131316 e649c4c4cb6f108eb1725e1b179739c61152e7e9
push id317
push userbbajaj@mozilla.com
push dateTue, 07 May 2013 01:20:33 +0000
treeherdermozilla-release@159a10910249 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqDot
bugs814579
milestone21.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 814579: connect client socket by id. r=qDot
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/SystemWorkerManager.cpp
dom/system/gonk/SystemWorkerManager.h
dom/system/gonk/nsISystemWorkerManager.idl
dom/system/gonk/ril_worker.js
ipc/ril/Ril.cpp
ipc/ril/Ril.h
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -326,17 +326,17 @@ function RadioInterfaceLayer() {
   this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
 
   this._targetMessageQueue = [];
 
   // pass debug pref to ril_worker
   this.worker.postMessage({rilMessageType: "setDebugEnabled",
                            enabled: debugPref});
 
-  gSystemWorkerManager.registerRilWorker(this.worker);
+  gSystemWorkerManager.registerRilWorker(0, this.worker);
 }
 RadioInterfaceLayer.prototype = {
 
   classID:   RADIOINTERFACELAYER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
                                     classDescription: "RadioInterfaceLayer",
                                     interfaces: [Ci.nsIRadioInterfaceLayer]}),
 
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -55,49 +55,61 @@ namespace {
 NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
 NS_DEFINE_CID(kNetworkManagerCID, NS_NETWORKMANAGER_CID);
 
 // Doesn't carry a reference, we're owned by services.
 SystemWorkerManager *gInstance = nullptr;
 
 class ConnectWorkerToRIL : public WorkerTask
 {
+  const unsigned long mClientId;
+
 public:
+  ConnectWorkerToRIL(unsigned long aClientId)
+    : mClientId(aClientId)
+  { }
+
   virtual bool RunTask(JSContext *aCx);
 };
 
 class SendRilSocketDataTask : public nsRunnable
 {
 public:
-  SendRilSocketDataTask(UnixSocketRawData *aRawData)
+  SendRilSocketDataTask(unsigned long aClientId,
+                        UnixSocketRawData *aRawData)
     : mRawData(aRawData)
+    , mClientId(aClientId)
   { }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
-    SystemWorkerManager::SendRilRawData(mRawData);
+    SystemWorkerManager::SendRilRawData(mClientId, mRawData);
     return NS_OK;
   }
 
 private:
   UnixSocketRawData *mRawData;
+  unsigned long mClientId;
 };
 
 JSBool
 PostToRIL(JSContext *cx, unsigned argc, jsval *vp)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
 
-  if (argc != 1) {
-    JS_ReportError(cx, "Expecting a single argument with the RIL message");
+  if (argc != 2) {
+    JS_ReportError(cx, "Expecting two arguments with the RIL message");
     return false;
   }
 
-  jsval v = JS_ARGV(cx, vp)[0];
+  jsval cv = JS_ARGV(cx, vp)[0];
+  int clientId = cv.toInt32();
+
+  jsval v = JS_ARGV(cx, vp)[1];
 
   JSAutoByteString abs;
   void *data;
   size_t size;
   if (JSVAL_IS_STRING(v)) {
     JSString *str = JSVAL_TO_STRING(v);
     if (!abs.encode(cx, str)) {
       return false;
@@ -126,30 +138,35 @@ PostToRIL(JSContext *cx, unsigned argc, 
     JS_ReportError(cx,
                    "Incorrect argument. Expecting a string or a typed array");
     return false;
   }
 
   UnixSocketRawData* raw = new UnixSocketRawData(size);
   memcpy(raw->mData, data, raw->mSize);
 
-  nsRefPtr<SendRilSocketDataTask> task = new SendRilSocketDataTask(raw);
+  nsRefPtr<SendRilSocketDataTask> task = new SendRilSocketDataTask(clientId, raw);
   NS_DispatchToMainThread(task);
   return true;
 }
 
 bool
 ConnectWorkerToRIL::RunTask(JSContext *aCx)
 {
   // Set up the postRILMessage on the function for worker -> RIL thread
   // communication.
   NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
   NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
   JSObject *workerGlobal = JS_GetGlobalObject(aCx);
 
+  if (!JS_DefineProperty(aCx, workerGlobal, "CLIENT_ID",
+                         INT_TO_JSVAL(mClientId), nullptr, nullptr, 0)) {
+    return false;
+  }
+
   return !!JS_DefineFunction(aCx, workerGlobal, "postRILMessage", PostToRIL, 1,
                              0);
 }
 
 #ifdef MOZ_WIDGET_GONK
 
 JSBool
 DoNetdCommand(JSContext *cx, unsigned argc, jsval *vp)
@@ -368,19 +385,21 @@ SystemWorkerManager::Shutdown()
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mShutdown = true;
 
 #ifdef MOZ_WIDGET_GONK
   ShutdownAutoMounter();
 #endif
 
-  if (mRilConsumer) {
-    mRilConsumer->Shutdown();
-    mRilConsumer = nullptr;
+  for (unsigned long i = 0; i < mRilConsumers.Length(); i++) {
+    if (mRilConsumers[i]) {
+      mRilConsumers[i]->Shutdown();
+      mRilConsumers[i] = nullptr;
+    }
   }
 
 #ifdef MOZ_WIDGET_GONK
   StopNetd();
   mNetdWorker = nullptr;
 #endif
 
   nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
@@ -421,24 +440,26 @@ SystemWorkerManager::FactoryCreate()
 // static
 nsIInterfaceRequestor*
 SystemWorkerManager::GetInterfaceRequestor()
 {
   return gInstance;
 }
 
 bool
-SystemWorkerManager::SendRilRawData(UnixSocketRawData* aRaw)
+SystemWorkerManager::SendRilRawData(unsigned long aClientId,
+                                    UnixSocketRawData* aRaw)
 {
-  if (!gInstance->mRilConsumer) {
+  if ((gInstance->mRilConsumers.Length() <= aClientId) ||
+      !gInstance->mRilConsumers[aClientId]) {
     // Probably shuting down.
     delete aRaw;
     return true;
   }
-  return gInstance->mRilConsumer->SendSocketData(aRaw);
+  return gInstance->mRilConsumers[aClientId]->SendSocketData(aRaw);
 }
 
 NS_IMETHODIMP
 SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (aIID.Equals(NS_GET_IID(nsIWifi))) {
@@ -453,37 +474,50 @@ SystemWorkerManager::GetInterface(const 
   }
 #endif
 
   NS_WARNING("Got nothing for the requested IID!");
   return NS_ERROR_NO_INTERFACE;
 }
 
 nsresult
-SystemWorkerManager::RegisterRilWorker(const JS::Value& aWorker,
+SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
+                                       const JS::Value& aWorker,
                                        JSContext *aCx)
 {
   NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(aWorker), NS_ERROR_UNEXPECTED);
 
+  if (!mRilConsumers.EnsureLengthAtLeast(aClientId + 1)) {
+    NS_WARNING("Failed to ensure minimum length of mRilConsumers");
+    return NS_ERROR_FAILURE;
+  }
+
+  if (mRilConsumers[aClientId]) {
+    NS_WARNING("RilConsumer already registered");
+    return NS_ERROR_FAILURE;
+  }
+
   JSAutoRequest ar(aCx);
   JSAutoCompartment ac(aCx, JSVAL_TO_OBJECT(aWorker));
 
   WorkerCrossThreadDispatcher *wctd =
     GetWorkerCrossThreadDispatcher(aCx, aWorker);
   if (!wctd) {
+    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for ril");
     return NS_ERROR_FAILURE;
   }
 
-  nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
+  nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL(aClientId);
   if (!wctd->PostTask(connection)) {
+    NS_WARNING("Failed to connect worker to ril");
     return NS_ERROR_UNEXPECTED;
   }
 
   // Now that we're set up, connect ourselves to the RIL thread.
-  mRilConsumer = new RilConsumer(wctd);
+  mRilConsumers[aClientId] = new RilConsumer(aClientId, wctd);
   return NS_OK;
 }
 
 #ifdef MOZ_WIDGET_GONK
 nsresult
 SystemWorkerManager::InitNetd(JSContext *cx)
 {
   nsCOMPtr<nsIWorkerHolder> worker = do_GetService(kNetworkManagerCID);
@@ -495,17 +529,17 @@ SystemWorkerManager::InitNetd(JSContext 
   NS_ENSURE_TRUE(!JSVAL_IS_PRIMITIVE(workerval), NS_ERROR_UNEXPECTED);
 
   JSAutoRequest ar(cx);
   JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(workerval));
 
   WorkerCrossThreadDispatcher *wctd =
     GetWorkerCrossThreadDispatcher(cx, workerval);
   if (!wctd) {
-    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher");
+    NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for netd");
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<ConnectWorkerToNetd> connection = new ConnectWorkerToNetd();
   if (!wctd->PostTask(connection)) {
     NS_WARNING("Failed to connect worker to netd");
     return NS_ERROR_UNEXPECTED;
   }
--- a/dom/system/gonk/SystemWorkerManager.h
+++ b/dom/system/gonk/SystemWorkerManager.h
@@ -54,33 +54,34 @@ public:
   void Shutdown();
 
   static already_AddRefed<SystemWorkerManager>
   FactoryCreate();
 
   static nsIInterfaceRequestor*
   GetInterfaceRequestor();
 
-  static bool SendRilRawData(ipc::UnixSocketRawData* aRaw);
+  static bool SendRilRawData(unsigned long aClientId,
+                             ipc::UnixSocketRawData* aRaw);
 
 private:
   SystemWorkerManager();
   ~SystemWorkerManager();
 
 #ifdef MOZ_WIDGET_GONK
   nsresult InitNetd(JSContext *cx);
 #endif
   nsresult InitWifi(JSContext *cx);
 
 #ifdef MOZ_WIDGET_GONK
   nsCOMPtr<nsIWorkerHolder> mNetdWorker;
 #endif
   nsCOMPtr<nsIWorkerHolder> mWifiWorker;
 
-  nsRefPtr<ipc::RilConsumer> mRilConsumer;
+  nsTArray<nsRefPtr<ipc::RilConsumer> > mRilConsumers;
 
   bool mShutdown;
 };
 
 }
 }
 }
 
--- a/dom/system/gonk/nsISystemWorkerManager.idl
+++ b/dom/system/gonk/nsISystemWorkerManager.idl
@@ -6,10 +6,11 @@
 
 /**
  * Information about networks that is exposed to network manager API consumers.
  */
 [scriptable, builtinclass, uuid(02166330-2ff6-4ea5-895a-693c0c2b4c1f)]
 interface nsISystemWorkerManager : nsISupports
 {
   [implicit_jscontext]
-  void registerRilWorker(in jsval aWorker);
+  void registerRilWorker(in unsigned long aClientId,
+                         in jsval aWorker);
 };
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -688,17 +688,17 @@ let Buf = {
     // the size itself.
     let parcelSize = this.outgoingIndex - PARCEL_SIZE_SIZE;
     this.writeParcelSize(parcelSize);
 
     // This assumes that postRILMessage will make a copy of the ArrayBufferView
     // right away!
     let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex);
     if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel));
-    postRILMessage(parcel);
+    postRILMessage(CLIENT_ID, parcel);
     this.outgoingIndex = PARCEL_SIZE_SIZE;
   },
 
   simpleRequest: function simpleRequest(type, options) {
     this.newParcel(type, options);
     this.sendParcel();
   }
 };
@@ -9945,17 +9945,17 @@ let ICCContactHelper = {
 
 /**
  * Global stuff.
  */
 
 if (!this.debug) {
   // Debugging stub that goes nowhere.
   this.debug = function debug(message) {
-    dump("RIL Worker: " + message + "\n");
+    dump("RIL Worker[" + CLIENT_ID + "]: " + message + "\n");
   };
 }
 
 // Initialize buffers. This is a separate function so that unit tests can
 // re-initialize the buffers at will.
 Buf.init();
 
 function onRILMessage(data) {
--- a/ipc/ril/Ril.cpp
+++ b/ipc/ril/Ril.cpp
@@ -58,27 +58,33 @@ DispatchRILEvent::RunTask(JSContext *aCx
     jsval argv[] = { OBJECT_TO_JSVAL(array) };
     return JS_CallFunctionName(aCx, obj, "onRILMessage", NS_ARRAY_LENGTH(argv),
                                argv, argv);
 }
 
 class RilConnector : public mozilla::ipc::UnixSocketConnector
 {
 public:
+  RilConnector(unsigned long aClientId) : mClientId(aClientId)
+  {}
+
   virtual ~RilConnector()
   {}
 
   virtual int Create();
   virtual void CreateAddr(bool aIsServer,
                           socklen_t& aAddrSize,
                           struct sockaddr *aAddr,
                           const char* aAddress);
   virtual bool SetUp(int aFd);
   virtual void GetSocketAddr(const sockaddr& aAddr,
                              nsAString& aAddrStr);
+
+private:
+  unsigned long mClientId;
 };
 
 int
 RilConnector::Create()
 {
     MOZ_ASSERT(!NS_IsMainThread());
 
     int fd = -1;
@@ -129,17 +135,17 @@ RilConnector::CreateAddr(bool aIsServer,
 
     hp = gethostbyname("localhost");
     if (!hp) {
         return;
     }
 
     memset(&addr_in, 0, sizeof(addr_in));
     addr_in.sin_family = hp->h_addrtype;
-    addr_in.sin_port = htons(RIL_TEST_PORT);
+    addr_in.sin_port = htons(RIL_TEST_PORT + mClientId);
     memcpy(&addr_in.sin_addr, hp->h_addr, hp->h_length);
 
     aAddrSize = sizeof(addr_in);
     memcpy(aAddr, &addr_in, aAddrSize);
 #endif
 }
 
 bool
@@ -157,21 +163,34 @@ RilConnector::GetSocketAddr(const sockad
     MOZ_NOT_REACHED("This should never be called!");
 }
 
 } // anonymous namespace
 
 namespace mozilla {
 namespace ipc {
 
-RilConsumer::RilConsumer(WorkerCrossThreadDispatcher* aDispatcher)
+RilConsumer::RilConsumer(unsigned long aClientId,
+                         WorkerCrossThreadDispatcher* aDispatcher)
     : mDispatcher(aDispatcher)
+    , mClientId(aClientId)
     , mShutdown(false)
 {
-    ConnectSocket(new RilConnector(), RIL_SOCKET_NAME);
+    // Only append client id after RIL_SOCKET_NAME when it's not connected to
+    // the first(0) rilproxy for compatibility.
+    if (!aClientId) {
+        mAddress = RIL_SOCKET_NAME;
+    } else {
+        struct sockaddr_un addr_un;
+        snprintf(addr_un.sun_path, sizeof addr_un.sun_path, "%s%lu",
+                 RIL_SOCKET_NAME, aClientId);
+        mAddress = addr_un.sun_path;
+    }
+
+    ConnectSocket(new RilConnector(mClientId), mAddress.get());
 }
 
 void
 RilConsumer::Shutdown()
 {
     mShutdown = true;
     CloseSocket();
 }
@@ -199,14 +218,14 @@ RilConsumer::OnConnectError()
     CloseSocket();
 }
 
 void
 RilConsumer::OnDisconnect()
 {
     LOG("%s\n", __FUNCTION__);
     if (!mShutdown) {
-        ConnectSocket(new RilConnector(), RIL_SOCKET_NAME, 1000);
+        ConnectSocket(new RilConnector(mClientId), mAddress.get(), 1000);
     }
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/ril/Ril.h
+++ b/ipc/ril/Ril.h
@@ -11,29 +11,32 @@
 #include <mozilla/ipc/UnixSocket.h>
 
 namespace mozilla {
 namespace ipc {
 
 class RilConsumer : public mozilla::ipc::UnixSocketConsumer
 {
 public:
-  RilConsumer(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
+  RilConsumer(unsigned long aClientId,
+              mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
   virtual ~RilConsumer() { }
 
   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;
+  unsigned long mClientId;
+  nsCString mAddress;
   bool mShutdown;
 };
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_Ril_h