--- a/dom/network/PUDPSocket.ipdl
+++ b/dom/network/PUDPSocket.ipdl
@@ -37,28 +37,30 @@ namespace net {
//-------------------------------------------------------------------
protocol PUDPSocket
{
manager PNecko or PBackground;
parent:
Bind(UDPAddressInfo addressInfo, bool addressReuse, bool loopback);
+ Connect(UDPAddressInfo addressInfo);
OutgoingData(UDPData data, UDPSocketAddr addr);
JoinMulticast(nsCString multicastAddress, nsCString iface);
LeaveMulticast(nsCString multicastAddress, nsCString iface);
Close();
RequestDelete();
child:
CallbackOpened(UDPAddressInfo addressInfo);
+ CallbackConnected(UDPAddressInfo addressInfo);
CallbackClosed();
CallbackReceivedData(UDPAddressInfo addressInfo, uint8_t[] data);
CallbackError(nsCString message, nsCString filename, uint32_t lineNumber);
__delete__();
};
} // namespace net
--- a/dom/network/UDPSocket.cpp
+++ b/dom/network/UDPSocket.cpp
@@ -735,16 +735,25 @@ UDPSocket::CallListenerOpened()
}
mOpened->MaybeResolve(JS::UndefinedHandleValue);
return NS_OK;
}
NS_IMETHODIMP
+UDPSocket::CallListenerConnected()
+{
+ // This shouldn't be called here.
+ MOZ_CRASH();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
UDPSocket::CallListenerClosed()
{
CloseWithReason(NS_OK);
return NS_OK;
}
} // namespace dom
--- a/dom/network/UDPSocketChild.cpp
+++ b/dom/network/UDPSocketChild.cpp
@@ -190,16 +190,28 @@ UDPSocketChild::Bind(nsIUDPSocketInterna
mFilterName);
}
SendBind(UDPAddressInfo(nsCString(aHost), aPort), aAddressReuse, aLoopback);
return NS_OK;
}
NS_IMETHODIMP
+UDPSocketChild::Connect(nsIUDPSocketInternal* aSocket, const nsACString & aHost, uint16_t aPort)
+{
+ UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
+
+ mSocket = aSocket;
+
+ SendConnect(UDPAddressInfo(nsCString(aHost), aPort));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
UDPSocketChild::Close()
{
SendClose();
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Send(const nsACString& aHost,
@@ -339,16 +351,30 @@ UDPSocketChild::RecvCallbackOpened(const
UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, mLocalAddress.get(), mLocalPort));
nsresult rv = mSocket->CallListenerOpened();
mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}
+// PUDPSocketChild Methods
+bool
+UDPSocketChild::RecvCallbackConnected(const UDPAddressInfo& aAddressInfo)
+{
+ mLocalAddress = aAddressInfo.addr();
+ mLocalPort = aAddressInfo.port();
+
+ UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, mLocalAddress.get(), mLocalPort));
+ nsresult rv = mSocket->CallListenerConnected();
+ mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
+
+ return true;
+}
+
bool
UDPSocketChild::RecvCallbackClosed()
{
nsresult rv = mSocket->CallListenerClosed();
mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
return true;
}
--- a/dom/network/UDPSocketChild.h
+++ b/dom/network/UDPSocketChild.h
@@ -40,16 +40,17 @@ public:
NS_IMETHOD_(MozExternalRefCountType) Release() override;
UDPSocketChild();
virtual ~UDPSocketChild();
nsresult CreatePBackgroundSpinUntilDone();
virtual bool RecvCallbackOpened(const UDPAddressInfo& aAddressInfo) override;
+ virtual bool RecvCallbackConnected(const UDPAddressInfo& aAddressInfo) override;
virtual bool RecvCallbackClosed() override;
virtual bool RecvCallbackReceivedData(const UDPAddressInfo& aAddressInfo,
InfallibleTArray<uint8_t>&& aData) override;
virtual bool RecvCallbackError(const nsCString& aMessage,
const nsCString& aFilename,
const uint32_t& aLineNumber) override;
private:
--- a/dom/network/UDPSocketParent.cpp
+++ b/dom/network/UDPSocketParent.cpp
@@ -95,17 +95,17 @@ UDPSocketParent::GetAppId()
bool
UDPSocketParent::Init(const IPC::Principal& aPrincipal,
const nsACString& aFilter)
{
MOZ_ASSERT_IF(mBackgroundManager, !aPrincipal);
// will be used once we move all UDPSocket to PBackground, or
// if we add in Principal checking for mtransport
Unused << mBackgroundManager;
-
+
mPrincipal = aPrincipal;
if (net::UsingNeckoIPCSecurity() &&
mPrincipal &&
!ContentParent::IgnoreIPCPrincipal()) {
if (mNeckoManager) {
if (!AssertAppPrincipal(mNeckoManager->Manager(), mPrincipal)) {
return false;
}
@@ -191,17 +191,17 @@ UDPSocketParent::RecvBind(const UDPAddre
}
nsresult
UDPSocketParent::BindInternal(const nsCString& aHost, const uint16_t& aPort,
const bool& aAddressReuse, const bool& aLoopback)
{
nsresult rv;
- UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, nsCString(aHost).get(), aPort));
+ UDPSOCKET_LOG(("%s: [this=%p] %s:%u addressReuse: %d loopback: %d", __FUNCTION__, this, nsCString(aHost).get(), aPort, aAddressReuse, aLoopback));
nsCOMPtr<nsIUDPSocket> sock =
do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -221,33 +221,89 @@ UDPSocketParent::BindInternal(const nsCS
rv = sock->InitWithAddress(&addr, mPrincipal, aAddressReuse,
/* optional_argc = */ 1);
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
+ /*
+ // TODO drno: Fails on IPv6 sockets?!
rv = sock->SetMulticastLoopback(aLoopback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
+ */
// register listener
rv = sock->AsyncListen(this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mSocket = sock;
return NS_OK;
}
bool
+UDPSocketParent::RecvConnect(const UDPAddressInfo& aAddressInfo) {
+ UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, aAddressInfo.addr().get(), aAddressInfo.port()));
+ if (NS_FAILED(ConnectInternal(aAddressInfo.addr(), aAddressInfo.port()))) {
+ FireInternalError(__LINE__);
+ return true;
+ }
+
+ nsCOMPtr<nsINetAddr> localAddr;
+ mSocket->GetLocalAddr(getter_AddRefs(localAddr));
+
+ nsCString addr;
+ if (NS_FAILED(localAddr->GetAddress(addr))) {
+ FireInternalError(__LINE__);
+ return true;
+ }
+
+ uint16_t port;
+ if (NS_FAILED(localAddr->GetPort(&port))) {
+ FireInternalError(__LINE__);
+ return true;
+ }
+
+ UDPSOCKET_LOG(("%s: SendCallbackConnected: %s:%u", __FUNCTION__, addr.get(), port));
+ mozilla::Unused << SendCallbackConnected(UDPAddressInfo(addr, port));
+
+ return true;
+}
+
+nsresult
+UDPSocketParent::ConnectInternal(const nsCString& aHost, const uint16_t& aPort)
+{
+ nsresult rv;
+
+ UDPSOCKET_LOG(("%s: %s:%u", __FUNCTION__, nsCString(aHost).get(), aPort));
+ PRNetAddr prAddr;
+ PR_InitializeNetAddr(PR_IpAddrAny, aPort, &prAddr);
+ PRStatus status = PR_StringToNetAddr(aHost.BeginReading(), &prAddr);
+ if (status != PR_SUCCESS) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mozilla::net::NetAddr addr;
+ PRNetAddrToNetAddr(&prAddr, &addr);
+
+ rv = mSocket->Connect(&addr);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+bool
UDPSocketParent::RecvOutgoingData(const UDPData& aData,
const UDPSocketAddr& aAddr)
{
MOZ_ASSERT(mSocket);
nsresult rv;
if (mFilter) {
// TODO, Bug 933102, filter packets that are sent with hostname.
--- a/dom/network/UDPSocketParent.h
+++ b/dom/network/UDPSocketParent.h
@@ -31,16 +31,17 @@ public:
explicit UDPSocketParent(PBackgroundParent* aManager);
explicit UDPSocketParent(PNeckoParent* aManager);
bool Init(const IPC::Principal& aPrincipal, const nsACString& aFilter);
virtual bool RecvBind(const UDPAddressInfo& aAddressInfo,
const bool& aAddressReuse, const bool& aLoopback) override;
+ virtual bool RecvConnect(const UDPAddressInfo& aAddressInfo) override;
virtual bool RecvOutgoingData(const UDPData& aData, const UDPSocketAddr& aAddr) override;
virtual bool RecvClose() override;
virtual bool RecvRequestDelete() override;
virtual bool RecvJoinMulticast(const nsCString& aMulticastAddress,
const nsCString& aInterface) override;
virtual bool RecvLeaveMulticast(const nsCString& aMulticastAddress,
@@ -51,17 +52,17 @@ public:
private:
virtual ~UDPSocketParent();
virtual void ActorDestroy(ActorDestroyReason why) override;
void Send(const InfallibleTArray<uint8_t>& aData, const UDPSocketAddr& aAddr);
void Send(const InputStreamParams& aStream, const UDPSocketAddr& aAddr);
nsresult BindInternal(const nsCString& aHost, const uint16_t& aPort,
const bool& aAddressReuse, const bool& aLoopback);
-
+ nsresult ConnectInternal(const nsCString& aHost, const uint16_t& aPort);
void FireInternalError(uint32_t aLineNo);
// One of these will be null and the other non-null.
PBackgroundParent* mBackgroundManager;
PNeckoParent* mNeckoManager;
bool mIPCOpen;
nsCOMPtr<nsIUDPSocket> mSocket;
--- a/dom/network/interfaces/nsIUDPSocketChild.idl
+++ b/dom/network/interfaces/nsIUDPSocketChild.idl
@@ -14,31 +14,34 @@ namespace mozilla {
namespace net {
union NetAddr;
}
}
%}
native NetAddr(mozilla::net::NetAddr);
[ptr] native NetAddrPtr(mozilla::net::NetAddr);
-[scriptable, uuid(481f15ce-224a-40b6-9927-7effbc326776)]
+[scriptable, uuid(1e6ad73b-6c05-4d78-9a88-2d357b88f58b)]
interface nsIUDPSocketChild : nsISupports
{
readonly attribute unsigned short localPort;
readonly attribute AUTF8String localAddress;
attribute AUTF8String filterName;
// Allow hosting this over PBackground instead of PNecko
[noscript] void setBackgroundSpinsEvents();
// Tell the chrome process to bind the UDP socket to a given local host and port
void bind(in nsIUDPSocketInternal socket, in nsIPrincipal principal,
in AUTF8String host, in unsigned short port,
in bool addressReuse, in bool loopback);
+ // Tell the chrome process to connect the UDP socket to a given remote host and port
+ void connect(in nsIUDPSocketInternal socket, in AUTF8String host, in unsigned short port);
+
// Tell the chrome process to perform equivalent operations to all following methods
void send(in AUTF8String host, in unsigned short port,
[const, array, size_is(byteLength)] in uint8_t bytes,
in unsigned long byteLength);
// Send without DNS query
void sendWithAddr(in nsINetAddr addr,
[const, array, size_is(byteLength)] in uint8_t bytes,
in unsigned long byteLength);
@@ -51,21 +54,23 @@ interface nsIUDPSocketChild : nsISupport
void close();
void joinMulticast(in AUTF8String multicastAddress, in AUTF8String iface);
void leaveMulticast(in AUTF8String multicastAddress, in AUTF8String iface);
};
/*
* Internal interface for callback from chrome process
*/
-[scriptable, uuid(44cd9ad5-d574-4169-baf9-e1af0648a143)]
+[scriptable, uuid(613dd3ad-598b-4da9-ad63-bbda50c20098)]
interface nsIUDPSocketInternal : nsISupports
{
// callback while socket is opened. localPort and localAddress is ready until this time.
void callListenerOpened();
+ // callback while socket is connected.
+ void callListenerConnected();
// callback while socket is closed.
void callListenerClosed();
// callback while incoming packet is received.
void callListenerReceivedData(in AUTF8String host, in unsigned short port,
[const, array, size_is(dataLength)] in uint8_t data,
in unsigned long dataLength);
// callback while any error happened.
void callListenerError(in AUTF8String message, in AUTF8String filename, in uint32_t lineNumber);
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -1039,16 +1039,22 @@ NS_IMETHODIMP NrUdpSocketIpcProxy::CallL
return socket_->CallListenerReceivedData(host, port, data, data_length);
}
// callback while UDP socket is opened
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerOpened() {
return socket_->CallListenerOpened();
}
+// callback while UDP socket is connected
+NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerConnected() {
+ return socket_->CallListenerConnected();
+ return NS_OK;
+}
+
// callback while UDP socket is closed
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerClosed() {
return socket_->CallListenerClosed();
}
// NrUdpSocketIpc Implementation
NrUdpSocketIpc::NrUdpSocketIpc()
: NrSocketIpc(GetIOThreadAndAddUse_s()),
@@ -1122,21 +1128,17 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListen
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::recv_callback_s,
msg),
NS_DISPATCH_NORMAL);
return NS_OK;
}
-// callback while UDP socket is opened
-NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
- ASSERT_ON_THREAD(io_thread_);
- ReentrantMonitorAutoEnter mon(monitor_);
-
+NS_IMETHODIMP NrUdpSocketIpc::SetAddress() {
uint16_t port;
if (NS_FAILED(socket_child_->GetLocalPort(&port))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local port");
return NS_OK;
}
nsAutoCString address;
@@ -1165,22 +1167,56 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListen
MOZ_ASSERT(false, "Failed to copy my_addr_");
}
if (nr_praddr_to_transport_addr(&praddr, &my_addr_, IPPROTO_UDP, 1)) {
err_ = true;
MOZ_ASSERT(false, "Failed to copy local host to my_addr_");
}
- if (nr_transport_addr_cmp(&expected_addr, &my_addr_,
+ if (!nr_transport_addr_is_wildcard(&expected_addr) &&
+ nr_transport_addr_cmp(&expected_addr, &my_addr_,
NR_TRANSPORT_ADDR_CMP_MODE_ADDR)) {
err_ = true;
MOZ_ASSERT(false, "Address of opened socket is not expected");
}
+ return NS_OK;
+}
+
+// callback while UDP socket is opened
+NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
+ ASSERT_ON_THREAD(io_thread_);
+ ReentrantMonitorAutoEnter mon(monitor_);
+
+ nsresult rv = SetAddress();
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ mon.NotifyAll();
+
+ return NS_OK;
+}
+
+// callback while UDP socket is connected
+NS_IMETHODIMP NrUdpSocketIpc::CallListenerConnected() {
+ ASSERT_ON_THREAD(io_thread_);
+
+ ReentrantMonitorAutoEnter mon(monitor_);
+
+ MOZ_ASSERT(state_ == NR_CONNECTED);
+
+ nsresult rv = SetAddress();
+ if (NS_FAILED(rv)) {
+ mon.NotifyAll();
+ return rv;
+ }
+
+ r_log(LOG_GENERIC, LOG_INFO, "Exit UDP socket connected");
mon.NotifyAll();
return NS_OK;
}
// callback while UDP socket is closed
NS_IMETHODIMP NrUdpSocketIpc::CallListenerClosed() {
ASSERT_ON_THREAD(io_thread_);
@@ -1274,16 +1310,18 @@ int NrUdpSocketIpc::sendto(const void *m
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::sendto_i,
addr, buf),
NS_DISPATCH_NORMAL);
return 0;
}
void NrUdpSocketIpc::close() {
+ r_log(LOG_GENERIC,LOG_DEBUG,"NrUdpSocketIpc::close()");
+
ASSERT_ON_THREAD(sts_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
state_ = NR_CLOSING;
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::close_i),
@@ -1346,18 +1384,46 @@ int NrUdpSocketIpc::getaddr(nr_transport
if (state_ != NR_CONNECTED) {
return R_INTERNAL;
}
return nr_transport_addr_copy(addrp, &my_addr_);
}
int NrUdpSocketIpc::connect(nr_transport_addr *addr) {
- MOZ_ASSERT(false);
- return R_INTERNAL;
+ int r,_status;
+ int32_t port;
+ nsCString host;
+
+ ReentrantMonitorAutoEnter mon(monitor_);
+ r_log(LOG_GENERIC, LOG_DEBUG, "NrUdpSocketIpc::connect(%s)", addr->as_string);
+
+ if ((r=nr_transport_addr_get_addrstring_and_port(addr, &host, &port))) {
+ ABORT(r);
+ }
+
+ RUN_ON_THREAD(io_thread_,
+ mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
+ &NrUdpSocketIpc::connect_i,
+ host, static_cast<uint16_t>(port)),
+ NS_DISPATCH_NORMAL);
+
+ // Wait until connect() completes.
+ mon.Wait();
+
+ r_log(LOG_GENERIC, LOG_DEBUG, "NrUdpSocketIpc::connect completed err_ = %s",
+ err_ ? "true" : "false");
+
+ if (err_) {
+ ABORT(R_INTERNAL);
+ }
+
+ _status=0;
+abort:
+ return _status;
}
int NrUdpSocketIpc::write(const void *msg, size_t len, size_t *written) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrUdpSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
@@ -1413,16 +1479,38 @@ void NrUdpSocketIpc::create_i(const nsAC
/* loopback = */ false))) {
err_ = true;
MOZ_ASSERT(false, "Failed to create UDP socket");
mon.NotifyAll();
return;
}
}
+void NrUdpSocketIpc::connect_i(const nsACString &host, const uint16_t port) {
+ ASSERT_ON_THREAD(io_thread_);
+ nsresult rv;
+ ReentrantMonitorAutoEnter mon(monitor_);
+
+ RefPtr<NrUdpSocketIpcProxy> proxy(new NrUdpSocketIpcProxy);
+ rv = proxy->Init(this);
+ if (NS_FAILED(rv)) {
+ err_ = true;
+ mon.NotifyAll();
+ return;
+ }
+
+ if (NS_FAILED(socket_child_->Connect(proxy, host, port))) {
+ err_ = true;
+ MOZ_ASSERT(false, "Failed to connect UDP socket");
+ mon.NotifyAll();
+ return;
+ }
+}
+
+
void NrUdpSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
if (!socket_child_) {
MOZ_ASSERT(false);
err_ = true;
--- a/media/mtransport/nr_socket_prsock.h
+++ b/media/mtransport/nr_socket_prsock.h
@@ -238,16 +238,17 @@ public:
NS_IMETHODIMP CallListenerError(const nsACString &message,
const nsACString &filename,
uint32_t line_number);
NS_IMETHODIMP CallListenerReceivedData(const nsACString &host,
uint16_t port,
const uint8_t *data,
uint32_t data_length);
NS_IMETHODIMP CallListenerOpened();
+ NS_IMETHODIMP CallListenerConnected();
NS_IMETHODIMP CallListenerClosed();
NrUdpSocketIpc();
// Implementations of the NrSocketBase APIs
virtual int create(nr_transport_addr *addr) override;
virtual int sendto(const void *msg, size_t len,
int flags, nr_transport_addr *to) override;
@@ -262,18 +263,21 @@ public:
virtual int listen(int backlog) override;
virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
private:
virtual ~NrUdpSocketIpc();
DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
+ nsresult SetAddress(); // Set the local address from parent info.
+
// Main or private thread executors of the NrSocketBase APIs
void create_i(const nsACString &host, const uint16_t port);
+ void connect_i(const nsACString &host, const uint16_t port);
void sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf);
void close_i();
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
static void release_child_i(nsIUDPSocketChild* aChild, nsCOMPtr<nsIEventTarget> ststhread);
static void release_use_s();
#endif
// STS thread executor
void recv_callback_s(RefPtr<nr_udp_message> msg);
--- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c
@@ -596,16 +596,18 @@ static int nr_ice_get_default_address(nr
if ((r=nr_socket_factory_create_socket(ctx->socket_factory, &addr, &sock)))
ABORT(r);
if ((r=nr_socket_connect(sock, &remote_addr)))
ABORT(r);
if ((r=nr_socket_getaddr(sock, addrp)))
ABORT(r);
+ r_log(LOG_GENERIC, LOG_DEBUG, "Default address: %s", addrp->as_string);
+
_status=0;
abort:
nr_socket_destroy(&sock);
return(_status);
}
static int nr_ice_get_default_local_address(nr_ice_ctx *ctx, int ip_version, nr_local_addr* addrs, int addr_ct, nr_local_addr *addrp)
{
--- a/netwerk/base/nsIUDPSocket.idl
+++ b/netwerk/base/nsIUDPSocket.idl
@@ -98,16 +98,26 @@ interface nsIUDPSocket : nsISupports
* transport (nsISocketTransport). See below for more details.
*
* @param aListener
* The listener to be notified when client connections are accepted.
*/
void asyncListen(in nsIUDPSocketListener aListener);
/**
+ * connect
+ *
+ * This method connects the UDP socket to a remote UDP address.
+ *
+ * @param aRemoteAddr
+ * The remote address to connect to
+ */
+ void connect([const] in NetAddrPtr aAddr);
+
+ /**
* Returns the local address of this UDP socket
*/
readonly attribute nsINetAddr localAddr;
/**
* Returns the port of this UDP socket.
*/
readonly attribute long port;
--- a/netwerk/base/nsUDPSocket.cpp
+++ b/netwerk/base/nsUDPSocket.cpp
@@ -664,16 +664,51 @@ nsUDPSocket::InitWithAddress(const NetAd
return NS_OK;
fail:
Close();
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
+nsUDPSocket::Connect(const NetAddr *aAddr)
+{
+ UDPSOCKET_LOG(("nsUDPSocket::Connect [this=%p]\n", this));
+
+ NS_ENSURE_ARG(aAddr);
+
+ PRNetAddr prAddr;
+ NetAddrToPRNetAddr(aAddr, &prAddr);
+
+ bool onSTSThread = false;
+ mSts->IsOnCurrentThread(&onSTSThread);
+ if (!onSTSThread) {
+ // TODO turn this into ASSERT
+ UDPSOCKET_LOG(("NOT ON STS THREAD"));
+ }
+
+ if (PR_Connect(mFD, &prAddr, PR_INTERVAL_NO_WAIT) != PR_SUCCESS) {
+ NS_WARNING("Cannot PR_Connect");
+ return NS_ERROR_FAILURE;
+ }
+
+ // get the resulting socket address, which may have been updated.
+ PRNetAddr addr;
+ if (PR_GetSockName(mFD, &addr) != PR_SUCCESS)
+ {
+ NS_WARNING("cannot get socket name");
+ return NS_ERROR_FAILURE;
+ }
+
+ PRNetAddrToNetAddr(&addr, &mAddr);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsUDPSocket::Close()
{
{
MutexAutoLock lock(mLock);
// we want to proxy the close operation to the socket thread if a listener
// has been set. otherwise, we should just close the socket here...
if (!mListener)
{