Bug 952927 - Part 1: Expose raw data on UDP socket messages. r=bz, r=mcmanus, r=schien
☠☠ backed out by a31e6b616085 ☠ ☠
authorPranav Kant <pranav913@gmail.com>
Fri, 07 Mar 2014 08:55:15 -0500
changeset 189740 14313e0ce5fdcc4a1ef9ea24db317f6393b3911f
parent 189739 39523a8931d55277e7a12689f05aaac4f773602e
child 189741 f74bf7d090ee231123a944a4a009213b36c989c8
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, mcmanus, schien
bugs952927
milestone30.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 952927 - Part 1: Expose raw data on UDP socket messages. r=bz, r=mcmanus, r=schien
netwerk/base/public/nsIUDPSocket.idl
netwerk/base/src/nsUDPSocket.cpp
netwerk/base/src/nsUDPSocket.h
--- a/netwerk/base/public/nsIUDPSocket.idl
+++ b/netwerk/base/public/nsIUDPSocket.idl
@@ -7,24 +7,26 @@
 
 interface nsINetAddr;
 interface nsIUDPSocketListener;
 interface nsIUDPMessage;
 interface nsISocketTransport;
 interface nsIOutputStream;
 
 %{ C++
+#include "nsTArrayForwardDeclare.h"
 namespace mozilla {
 namespace net {
 union NetAddr;
 }
 }
 %}
 native NetAddr(mozilla::net::NetAddr);
 [ptr] native NetAddrPtr(mozilla::net::NetAddr);
+[ref] native Uint8TArrayRef(FallibleTArray<uint8_t>);
 
 /**
  * nsIUDPSocket
  *
  * An interface to a UDP socket that can accept incoming connections.
  */
 [scriptable, uuid(6EFE692D-F0B0-4A9E-9E63-837C7452446D)]
 interface nsIUDPSocket : nsISupports
@@ -203,9 +205,15 @@ interface nsIUDPMessage : nsISupports
      * Data of the message
      */
     readonly attribute ACString data;
 
     /**
      * Stream to send a response
      */
     readonly attribute nsIOutputStream outputStream;
+
+    /**
+     * Raw Data of the message
+     */
+    [implicit_jscontext] readonly attribute jsval rawData;
+    [noscript, notxpcom, nostdcall] Uint8TArrayRef getDataAsTArray();
 };
--- a/netwerk/base/src/nsUDPSocket.cpp
+++ b/netwerk/base/src/nsUDPSocket.cpp
@@ -1,15 +1,17 @@
 /* vim:set ts=2 sw=2 et cindent: */
 /* 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 "mozilla/Attributes.h"
 #include "mozilla/Endian.h"
+#include "mozilla/dom/TypedArray.h"
+#include "mozilla/HoldDropJSObjects.h"
 
 #include "nsSocketTransport2.h"
 #include "nsUDPSocket.h"
 #include "nsProxyRelease.h"
 #include "nsAutoPtr.h"
 #include "nsError.h"
 #include "nsNetCID.h"
 #include "prnetdb.h"
@@ -134,60 +136,101 @@ NS_IMETHODIMP nsUDPOutputStream::IsNonBl
 {
   *_retval = true;
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsUDPMessage impl
 //-----------------------------------------------------------------------------
-NS_IMPL_ISUPPORTS1(nsUDPMessage, nsIUDPMessage)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsUDPMessage)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsUDPMessage)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsUDPMessage)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsUDPMessage)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsIUDPMessage)
+NS_INTERFACE_MAP_END
 
-nsUDPMessage::nsUDPMessage(PRNetAddr* aAddr,
-             nsIOutputStream* aOutputStream,
-             const nsACString& aData)
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsUDPMessage)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJsobj)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsUDPMessage)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsUDPMessage)
+  tmp->mJsobj = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+nsUDPMessage::nsUDPMessage(NetAddr* aAddr,
+                           nsIOutputStream* aOutputStream,
+                           FallibleTArray<uint8_t>& aData)
   : mOutputStream(aOutputStream)
-  , mData(aData)
 {
   memcpy(&mAddr, aAddr, sizeof(NetAddr));
+  aData.SwapElements(mData);
 }
 
 nsUDPMessage::~nsUDPMessage()
 {
+  mozilla::DropJSObjects(this);
 }
 
 /* readonly attribute nsINetAddr from; */
-NS_IMETHODIMP nsUDPMessage::GetFromAddr(nsINetAddr * *aFromAddr)
+NS_IMETHODIMP
+nsUDPMessage::GetFromAddr(nsINetAddr * *aFromAddr)
 {
   NS_ENSURE_ARG_POINTER(aFromAddr);
 
-  NetAddr clientAddr;
-  PRNetAddrToNetAddr(&mAddr, &clientAddr);
-
-  nsCOMPtr<nsINetAddr> result = new nsNetAddr(&clientAddr);
+  nsCOMPtr<nsINetAddr> result = new nsNetAddr(&mAddr);
   result.forget(aFromAddr);
 
   return NS_OK;
 }
 
 /* readonly attribute ACString data; */
-NS_IMETHODIMP nsUDPMessage::GetData(nsACString & aData)
+NS_IMETHODIMP
+nsUDPMessage::GetData(nsACString & aData)
 {
-  aData = mData;
+  aData.Assign(reinterpret_cast<const char*>(mData.Elements()), mData.Length());
   return NS_OK;
 }
 
 /* readonly attribute nsIOutputStream outputStream; */
-NS_IMETHODIMP nsUDPMessage::GetOutputStream(nsIOutputStream * *aOutputStream)
+NS_IMETHODIMP
+nsUDPMessage::GetOutputStream(nsIOutputStream * *aOutputStream)
 {
   NS_ENSURE_ARG_POINTER(aOutputStream);
   NS_IF_ADDREF(*aOutputStream = mOutputStream);
   return NS_OK;
 }
 
+/* readonly attribute jsval rawData; */
+NS_IMETHODIMP
+nsUDPMessage::GetRawData(JSContext* cx,
+                         JS::MutableHandleValue aRawData)
+{
+  if(!mJsobj){
+    mJsobj = mozilla::dom::Uint8Array::Create(cx, nullptr, mData.Length(), mData.Elements());
+    mozilla::HoldJSObjects(this);
+  }
+  aRawData.setObject(*mJsobj);
+  return NS_OK;
+}
+
+/* [noscript, notxpcom, nostdcall] Uint8ArrayRef getDataAsTArray(); */
+FallibleTArray<uint8_t>&
+nsUDPMessage::GetDataAsTArray()
+{
+  return mData;
+}
+
 //-----------------------------------------------------------------------------
 // nsUDPSocket
 //-----------------------------------------------------------------------------
 
 nsUDPSocket::nsUDPSocket()
   : mLock("nsUDPSocket.mLock")
   , mFD(nullptr)
   , mAttached(false)
@@ -298,16 +341,88 @@ nsUDPSocket::TryAttach()
 
   //
   // now, configure our poll flags for listening...
   //
   mPollFlags = (PR_POLL_READ | PR_POLL_EXCEPT);
   return NS_OK;
 }
 
+namespace {
+//-----------------------------------------------------------------------------
+// UDPMessageProxy
+//-----------------------------------------------------------------------------
+class UDPMessageProxy MOZ_FINAL : public nsIUDPMessage
+{
+public:
+  UDPMessageProxy(NetAddr* aAddr,
+                  nsIOutputStream* aOutputStream,
+                  FallibleTArray<uint8_t>& aData)
+  : mOutputStream(aOutputStream)
+  {
+    memcpy(&mAddr, aAddr, sizeof(NetAddr));
+    aData.SwapElements(mData);
+  }
+
+  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_NSIUDPMESSAGE
+
+private:
+  NetAddr mAddr;
+  nsCOMPtr<nsIOutputStream> mOutputStream;
+  FallibleTArray<uint8_t> mData;
+};
+
+NS_IMPL_ISUPPORTS1(UDPMessageProxy, nsIUDPMessage)
+
+/* readonly attribute nsINetAddr from; */
+NS_IMETHODIMP
+UDPMessageProxy::GetFromAddr(nsINetAddr * *aFromAddr)
+{
+  NS_ENSURE_ARG_POINTER(aFromAddr);
+
+  nsCOMPtr<nsINetAddr> result = new nsNetAddr(&mAddr);
+  result.forget(aFromAddr);
+
+  return NS_OK;
+}
+
+/* readonly attribute ACString data; */
+NS_IMETHODIMP
+UDPMessageProxy::GetData(nsACString & aData)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* [noscript, notxpcom, nostdcall] Uint8TArrayRef getDataAsTArray(); */
+FallibleTArray<uint8_t>&
+UDPMessageProxy::GetDataAsTArray()
+{
+  return mData;
+}
+
+/* readonly attribute jsval rawData; */
+NS_IMETHODIMP
+UDPMessageProxy::GetRawData(JSContext* cx,
+                            JS::MutableHandleValue aRawData)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute nsIOutputStream outputStream; */
+NS_IMETHODIMP
+UDPMessageProxy::GetOutputStream(nsIOutputStream * *aOutputStream)
+{
+  NS_ENSURE_ARG_POINTER(aOutputStream);
+  NS_IF_ADDREF(*aOutputStream = mOutputStream);
+  return NS_OK;
+}
+
+} //anonymous namespace
+
 //-----------------------------------------------------------------------------
 // nsUDPSocket::nsASocketHandler
 //-----------------------------------------------------------------------------
 
 void
 nsUDPSocket::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
 {
   NS_ASSERTION(NS_SUCCEEDED(mCondition), "oops");
@@ -328,19 +443,19 @@ nsUDPSocket::OnSocketReady(PRFileDesc *f
 
   if (count < 1) {
     NS_WARNING("error of recvfrom on UDP socket");
     mCondition = NS_ERROR_UNEXPECTED;
     return;
   }
   mByteReadCount += count;
 
-  nsCString data;
-  if (!data.Assign(buff, count, mozilla::fallible_t())) {
-    mCondition = NS_ERROR_OUT_OF_MEMORY;
+  FallibleTArray<uint8_t> data;
+  if(!data.AppendElements(buff, count)){
+    mCondition = NS_ERROR_UNEXPECTED;
     return;
   }
 
   nsCOMPtr<nsIAsyncInputStream> pipeIn;
   nsCOMPtr<nsIAsyncOutputStream> pipeOut;
 
   uint32_t segsize = 1400;
   uint32_t segcount = 0;
@@ -355,17 +470,19 @@ nsUDPSocket::OnSocketReady(PRFileDesc *f
   nsCOMPtr<nsUDPOutputStream> os = new nsUDPOutputStream(this, mFD, prClientAddr);
   rv = NS_AsyncCopy(pipeIn, os, mSts,
                     NS_ASYNCCOPY_VIA_READSEGMENTS, 1400);
 
   if (NS_FAILED(rv)) {
     return;
   }
 
-  nsCOMPtr<nsIUDPMessage> message = new nsUDPMessage(&prClientAddr, pipeOut, data);
+  NetAddr netAddr;
+  PRNetAddrToNetAddr(&prClientAddr, &netAddr);
+  nsCOMPtr<nsIUDPMessage> message = new UDPMessageProxy(&netAddr, pipeOut, data);
   mListener->OnPacketReceived(this, message);
 }
 
 void
 nsUDPSocket::OnSocketDetached(PRFileDesc *fd)
 {
   // force a failure condition if none set; maybe the STS is shutting down :-/
   if (NS_SUCCEEDED(mCondition))
@@ -529,17 +646,19 @@ NS_IMETHODIMP
 nsUDPSocket::GetAddress(NetAddr *aResult)
 {
   // no need to enter the lock here
   memcpy(aResult, &mAddr, sizeof(mAddr));
   return NS_OK;
 }
 
 namespace {
-
+//-----------------------------------------------------------------------------
+// SocketListenerProxy
+//-----------------------------------------------------------------------------
 class SocketListenerProxy MOZ_FINAL : public nsIUDPSocketListener
 {
 public:
   SocketListenerProxy(nsIUDPSocketListener* aListener)
     : mListener(new nsMainThreadPtrHolder<nsIUDPSocketListener>(aListener))
     , mTargetThread(do_GetCurrentThread())
   { }
 
@@ -608,17 +727,30 @@ SocketListenerProxy::OnStopListening(nsI
   nsRefPtr<OnStopListeningRunnable> r =
     new OnStopListeningRunnable(mListener, aSocket, aStatus);
   return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
 }
 
 NS_IMETHODIMP
 SocketListenerProxy::OnPacketReceivedRunnable::Run()
 {
-  mListener->OnPacketReceived(mSocket, mMessage);
+  NetAddr netAddr;
+  nsCOMPtr<nsINetAddr> nsAddr;
+  mMessage->GetFromAddr(getter_AddRefs(nsAddr));
+  nsAddr->GetNetAddr(&netAddr);
+
+  nsCOMPtr<nsIOutputStream> outputStream;
+  mMessage->GetOutputStream(getter_AddRefs(outputStream));
+
+  FallibleTArray<uint8_t>& data = mMessage->GetDataAsTArray();
+
+  nsCOMPtr<nsIUDPMessage> message = new nsUDPMessage(&netAddr,
+                                                     outputStream,
+                                                     data);
+  mListener->OnPacketReceived(mSocket, message);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SocketListenerProxy::OnStopListeningRunnable::Run()
 {
   mListener->OnStopListening(mSocket, mStatus);
   return NS_OK;
--- a/netwerk/base/src/nsUDPSocket.h
+++ b/netwerk/base/src/nsUDPSocket.h
@@ -5,16 +5,17 @@
 
 #ifndef nsUDPSocket_h__
 #define nsUDPSocket_h__
 
 #include "nsIUDPSocket.h"
 #include "mozilla/Mutex.h"
 #include "nsIOutputStream.h"
 #include "nsAutoPtr.h"
+#include "nsCycleCollectionParticipant.h"
 
 //-----------------------------------------------------------------------------
 
 class nsUDPSocket : public nsASocketHandler
                   , public nsIUDPSocket
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
@@ -56,29 +57,31 @@ private:
   uint64_t   mByteWriteCount;
 };
 
 //-----------------------------------------------------------------------------
 
 class nsUDPMessage : public nsIUDPMessage
 {
 public:
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsUDPMessage)
   NS_DECL_NSIUDPMESSAGE
 
-  nsUDPMessage(PRNetAddr* aAddr,
+  nsUDPMessage(mozilla::net::NetAddr* aAddr,
                nsIOutputStream* aOutputStream,
-               const nsACString& aData);
+               FallibleTArray<uint8_t>& aData);
 
 private:
   virtual ~nsUDPMessage();
 
-  PRNetAddr mAddr;
+  mozilla::net::NetAddr mAddr;
   nsCOMPtr<nsIOutputStream> mOutputStream;
-  nsCString mData;
+  FallibleTArray<uint8_t> mData;
+  JS::Heap<JSObject*> mJsobj;
 };
 
 
 //-----------------------------------------------------------------------------
 
 class nsUDPOutputStream : public nsIOutputStream
 {
 public: