Bug 951677 - Part 1: Add Bind function to SocketTransport. r=honzab
--- 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); }