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 209130 8d52ce400c01ec33ffa9d2682f3e9dec8e36537f
parent 209129 c890e0fa846d02d879547df458a9d6c25e540cbc
child 209131 27626f68637d6c531ba0836dce5b8785e5d39510
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewershonzab
bugs951677
milestone35.0a1
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); }