Bug 951677 - Part 1: Add Bind function to SocketTransport. r=honzab
authorPatrick Wang (Chih-Kai Wang) <kk1fff@patrickz.net>
Tue, 07 Oct 2014 17:24:57 +0800
changeset 232345 8d52ce400c01ec33ffa9d2682f3e9dec8e36537f
parent 232344 c890e0fa846d02d879547df458a9d6c25e540cbc
child 232346 27626f68637d6c531ba0836dce5b8785e5d39510
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab
bugs951677
milestone35.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 951677 - Part 1: Add Bind function to SocketTransport. r=honzab
netwerk/base/public/nsISocketTransport.idl
netwerk/base/src/nsSocketTransport2.cpp
netwerk/base/src/nsSocketTransport2.h
netwerk/protocol/http/TunnelUtils.cpp
--- a/netwerk/base/public/nsISocketTransport.idl
+++ b/netwerk/base/public/nsISocketTransport.idl
@@ -11,28 +11,29 @@ interface nsINetAddr;
 %{ C++
 namespace mozilla {
 namespace net {
 union NetAddr;
 }
 }
 %}
 native NetAddr(mozilla::net::NetAddr);
+[ptr] native NetAddrPtr(mozilla::net::NetAddr);
 
 /**
  * nsISocketTransport
  *
  * NOTE: Connection setup is triggered by opening an input or output stream,
  * it does not start on its own. Completion of the connection setup is
  * indicated by a STATUS_CONNECTED_TO notification to the event sink (if set).
  *
  * NOTE: This is a free-threaded interface, meaning that the methods on
  * this interface may be called from any thread.
  */
-[scriptable, uuid(3F41704C-CD5D-4537-8C4C-7B2EBFC5D972)]
+[scriptable, uuid(a0b3b547-d6f0-4b65-a3de-a99ffa368840)]
 interface nsISocketTransport : nsITransport 
 {
     /**
      * Get the peer's host for the underlying socket connection.
      * For Unix domain sockets, this is a pathname, or the empty string for
      * unnamed and abstract socket addresses.
      */
     readonly attribute AUTF8String host;
@@ -51,16 +52,21 @@ interface nsISocketTransport : nsITransp
 
     /**
      * Returns the IP address of the initiating end. This attribute
      * is defined only once a connection has been established.
      */
     [noscript] NetAddr getSelfAddr();
 
     /**
+     * Bind to a specific local address.
+     */
+    [noscript] void bind(in NetAddrPtr aLocalAddr);
+
+    /**
      * Returns a scriptable version of getPeerAddr. This attribute is defined
      * only once a connection has been established.
      */
     nsINetAddr getScriptablePeerAddr();
 
     /**
      * Returns a scriptable version of getSelfAddr. This attribute is defined
      * only once a connection has been established.
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -1350,16 +1350,28 @@ nsSocketTransport::InitiateSocket()
         SOCKET_LOG(("  trying address: %s\n", buf));
     }
 #endif
 
     //
     // Initiate the connect() to the host...
     //
     PRNetAddr prAddr;
+    {
+        if (mBindAddr) {
+            MutexAutoLock lock(mLock);
+            NetAddrToPRNetAddr(mBindAddr.get(), &prAddr);
+            status = PR_Bind(fd, &prAddr);
+            if (status != PR_SUCCESS) {
+                return NS_ERROR_FAILURE;
+            }
+            mBindAddr = nullptr;
+        }
+    }
+
     NetAddrToPRNetAddr(&mNetAddr, &prAddr);
 
     MOZ_EVENT_TRACER_EXEC(this, "net::tcp::connect");
     status = PR_Connect(fd, &prAddr, NS_SOCKET_CONNECT_TIMEOUT);
     if (status == PR_SUCCESS) {
         // 
         // we are connected!
         //
@@ -2216,16 +2228,32 @@ nsSocketTransport::GetSelfAddr(NetAddr *
 
     nsresult rv =
         (PR_GetSockName(fd, &prAddr) == PR_SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
     PRNetAddrToNetAddr(&prAddr, addr);
 
     return rv;
 }
 
+NS_IMETHODIMP
+nsSocketTransport::Bind(NetAddr *aLocalAddr)
+{
+    NS_ENSURE_ARG(aLocalAddr);
+
+    MutexAutoLock lock(mLock);
+    if (mAttached) {
+        return NS_ERROR_FAILURE;
+    }
+
+    mBindAddr = new NetAddr();
+    memcpy(mBindAddr.get(), aLocalAddr, sizeof(NetAddr));
+
+    return NS_OK;
+}
+
 /* nsINetAddr getScriptablePeerAddr (); */
 NS_IMETHODIMP
 nsSocketTransport::GetScriptablePeerAddr(nsINetAddr * *addr)
 {
     NetAddr rawAddr;
 
     nsresult rv;
     rv = GetPeerAddr(&rawAddr);
--- a/netwerk/base/src/nsSocketTransport2.h
+++ b/netwerk/base/src/nsSocketTransport2.h
@@ -300,16 +300,18 @@ private:
     nsCOMPtr<nsICancelable> mDNSRequest;
     nsCOMPtr<nsIDNSRecord>  mDNSRecord;
 
     // mNetAddr is valid from GetPeerAddr() once we have
     // reached STATE_TRANSFERRING. It must not change after that.
     mozilla::net::NetAddr   mNetAddr;
     bool                    mNetAddrIsSet;
 
+    nsAutoPtr<mozilla::net::NetAddr> mBindAddr;
+
     // socket methods (these can only be called on the socket thread):
 
     void     SendStatus(nsresult status);
     nsresult ResolveHost();
     nsresult BuildSocket(PRFileDesc *&, bool &, bool &); 
     nsresult InitiateSocket();
     bool     RecoverFromError();
 
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -1539,16 +1539,22 @@ SocketTransportShim::Close(nsresult aRea
 }
 
 NS_IMETHODIMP
 SocketTransportShim::SetEventSink(nsITransportEventSink *aSink, nsIEventTarget *aEventTarget)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+SocketTransportShim::Bind(NetAddr *aLocalAddr)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 #define FWD_TS_PTR(fx, ts) NS_IMETHODIMP \
 SocketTransportShim::fx(ts *arg) { return mWrapped->fx(arg); }
 
 #define FWD_TS_ADDREF(fx, ts) NS_IMETHODIMP \
 SocketTransportShim::fx(ts **arg) { return mWrapped->fx(arg); }
 
 #define FWD_TS(fx, ts) NS_IMETHODIMP \
 SocketTransportShim::fx(ts arg) { return mWrapped->fx(arg); }