mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 745283 - Part 1: Expose nsINetAddr for the local address of nsUDPSocket and support send with InputStream. r=jduell, r=mayhemer
--HG-- rename : netwerk/test/unit/test_bug952927.js => netwerk/test/unit/test_udpsocket.js
This commit is contained in:
parent
2fd5c32bc6
commit
3b55c8951a
@ -10,6 +10,7 @@ interface nsIUDPSocketListener;
|
||||
interface nsIUDPMessage;
|
||||
interface nsISocketTransport;
|
||||
interface nsIOutputStream;
|
||||
interface nsIInputStream;
|
||||
|
||||
%{ C++
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
@ -28,7 +29,7 @@ native NetAddr(mozilla::net::NetAddr);
|
||||
*
|
||||
* An interface to a UDP socket that can accept incoming connections.
|
||||
*/
|
||||
[scriptable, uuid(3240F793-80FA-4088-987A-9C7378F0AC88)]
|
||||
[scriptable, uuid(5e526cc7-a65f-42b2-b193-a6894c0253f7)]
|
||||
interface nsIUDPSocket : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -44,8 +45,11 @@ interface nsIUDPSocket : nsISupports
|
||||
* local loopback interface. Otherwise, it will accept connections
|
||||
* from any interface. To specify a particular network interface,
|
||||
* use initWithAddress.
|
||||
* @param aAddressReuse
|
||||
* If true, the socket is allowed to be bound to an address that is
|
||||
* already in use. Default is true.
|
||||
*/
|
||||
void init(in long aPort, in boolean aLoopbackOnly);
|
||||
[optional_argc] void init(in long aPort, in boolean aLoopbackOnly, [optional] in boolean aAddressReuse);
|
||||
|
||||
/**
|
||||
* initWithAddress
|
||||
@ -55,8 +59,11 @@ interface nsIUDPSocket : nsISupports
|
||||
*
|
||||
* @param aAddr
|
||||
* The address to which this UDP socket should be bound.
|
||||
* @param aAddressReuse
|
||||
* If true, the socket is allowed to be bound to an address that is
|
||||
* already in use. Default is true.
|
||||
*/
|
||||
[noscript] void initWithAddress([const] in NetAddrPtr aAddr);
|
||||
[noscript, optional_argc] void initWithAddress([const] in NetAddrPtr aAddr, [optional] in boolean aAddressReuse);
|
||||
|
||||
/**
|
||||
* close
|
||||
@ -85,6 +92,11 @@ interface nsIUDPSocket : nsISupports
|
||||
*/
|
||||
void asyncListen(in nsIUDPSocketListener aListener);
|
||||
|
||||
/**
|
||||
* Returns the local address of this UDP socket
|
||||
*/
|
||||
readonly attribute nsINetAddr localAddr;
|
||||
|
||||
/**
|
||||
* Returns the port of this UDP socket.
|
||||
*/
|
||||
@ -145,6 +157,29 @@ interface nsIUDPSocket : nsISupports
|
||||
[const, array, size_is(dataLength)]in uint8_t data,
|
||||
in unsigned long dataLength);
|
||||
|
||||
/**
|
||||
* sendBinaryStream
|
||||
*
|
||||
* Send out the datagram to specified remote address and port.
|
||||
*
|
||||
* @param host The remote host name.
|
||||
* @param port The remote port.
|
||||
* @param stream The input stream to be sent. This must be a buffered stream implementation.
|
||||
*/
|
||||
void sendBinaryStream(in AUTF8String host, in unsigned short port,
|
||||
in nsIInputStream stream);
|
||||
|
||||
/**
|
||||
* sendBinaryStreamWithAddress
|
||||
*
|
||||
* Send out the datagram to specified remote address and port.
|
||||
*
|
||||
* @param addr The remote host address.
|
||||
* @param stream The input stream to be sent. This must be a buffered stream implementation.
|
||||
*/
|
||||
void sendBinaryStreamWithAddress([const] in NetAddrPtr addr,
|
||||
in nsIInputStream stream);
|
||||
|
||||
/**
|
||||
* joinMulticast
|
||||
*
|
||||
|
@ -31,6 +31,7 @@ using namespace mozilla::net;
|
||||
using namespace mozilla;
|
||||
|
||||
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
||||
static const uint32_t UDP_PACKET_CHUNK_SIZE = 1400;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -479,7 +480,7 @@ nsUDPSocket::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
|
||||
nsCOMPtr<nsIAsyncInputStream> pipeIn;
|
||||
nsCOMPtr<nsIAsyncOutputStream> pipeOut;
|
||||
|
||||
uint32_t segsize = 1400;
|
||||
uint32_t segsize = UDP_PACKET_CHUNK_SIZE;
|
||||
uint32_t segcount = 0;
|
||||
net_ResolveSegmentParams(segsize, segcount);
|
||||
nsresult rv = NS_NewPipe2(getter_AddRefs(pipeIn), getter_AddRefs(pipeOut),
|
||||
@ -491,7 +492,7 @@ nsUDPSocket::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
|
||||
|
||||
nsRefPtr<nsUDPOutputStream> os = new nsUDPOutputStream(this, mFD, prClientAddr);
|
||||
rv = NS_AsyncCopy(pipeIn, os, mSts,
|
||||
NS_ASYNCCOPY_VIA_READSEGMENTS, 1400);
|
||||
NS_ASYNCCOPY_VIA_READSEGMENTS, UDP_PACKET_CHUNK_SIZE);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
@ -552,7 +553,7 @@ NS_IMPL_ISUPPORTS(nsUDPSocket, nsIUDPSocket)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUDPSocket::Init(int32_t aPort, bool aLoopbackOnly)
|
||||
nsUDPSocket::Init(int32_t aPort, bool aLoopbackOnly, bool aAddressReuse, uint8_t aOptionalArgc)
|
||||
{
|
||||
NetAddr addr;
|
||||
|
||||
@ -567,14 +568,16 @@ nsUDPSocket::Init(int32_t aPort, bool aLoopbackOnly)
|
||||
else
|
||||
addr.inet.ip = htonl(INADDR_ANY);
|
||||
|
||||
return InitWithAddress(&addr);
|
||||
return InitWithAddress(&addr, aAddressReuse, aOptionalArgc);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUDPSocket::InitWithAddress(const NetAddr *aAddr)
|
||||
nsUDPSocket::InitWithAddress(const NetAddr *aAddr, bool aAddressReuse, uint8_t aOptionalArgc)
|
||||
{
|
||||
NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
bool addressReuse = (aOptionalArgc == 1) ? aAddressReuse : true;
|
||||
|
||||
//
|
||||
// configure listening socket...
|
||||
//
|
||||
@ -598,7 +601,7 @@ nsUDPSocket::InitWithAddress(const NetAddr *aAddr)
|
||||
// to port 0 with SO_REUSEADDR
|
||||
if (port) {
|
||||
opt.option = PR_SockOpt_Reuseaddr;
|
||||
opt.value.reuse_addr = true;
|
||||
opt.value.reuse_addr = addressReuse;
|
||||
PR_SetSocketOption(mFD, &opt);
|
||||
}
|
||||
|
||||
@ -668,6 +671,17 @@ nsUDPSocket::GetPort(int32_t *aResult)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUDPSocket::GetLocalAddr(nsINetAddr * *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
nsCOMPtr<nsINetAddr> result = new nsNetAddr(&mAddr);
|
||||
result.forget(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUDPSocket::GetAddress(NetAddr *aResult)
|
||||
{
|
||||
@ -829,6 +843,47 @@ PendingSend::OnLookupComplete(nsICancelable *request,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class PendingSendStream : public nsIDNSListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
|
||||
PendingSendStream(nsUDPSocket *aSocket, uint16_t aPort,
|
||||
nsIInputStream *aStream)
|
||||
: mSocket(aSocket)
|
||||
, mPort(aPort)
|
||||
, mStream(aStream) {}
|
||||
|
||||
private:
|
||||
virtual ~PendingSendStream() {}
|
||||
|
||||
nsRefPtr<nsUDPSocket> mSocket;
|
||||
uint16_t mPort;
|
||||
nsCOMPtr<nsIInputStream> mStream;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(PendingSendStream, nsIDNSListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
PendingSendStream::OnLookupComplete(nsICancelable *request,
|
||||
nsIDNSRecord *rec,
|
||||
nsresult status)
|
||||
{
|
||||
if (NS_FAILED(status)) {
|
||||
NS_WARNING("Failed to send UDP packet due to DNS lookup failure");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NetAddr addr;
|
||||
if (NS_SUCCEEDED(rec->GetNextAddr(mPort, &addr))) {
|
||||
nsresult rv = mSocket->SendBinaryStreamWithAddress(&addr, mStream);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class SendRequestRunnable: public nsRunnable {
|
||||
public:
|
||||
SendRequestRunnable(nsUDPSocket *aSocket,
|
||||
@ -953,6 +1008,32 @@ nsUDPSocket::SendWithAddress(const NetAddr *aAddr, const uint8_t *aData,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUDPSocket::SendBinaryStream(const nsACString &aHost, uint16_t aPort,
|
||||
nsIInputStream *aStream)
|
||||
{
|
||||
NS_ENSURE_ARG(aStream);
|
||||
|
||||
nsCOMPtr<nsIDNSListener> listener = new PendingSendStream(this, aPort, aStream);
|
||||
|
||||
return ResolveHost(aHost, listener);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsUDPSocket::SendBinaryStreamWithAddress(const NetAddr *aAddr, nsIInputStream *aStream)
|
||||
{
|
||||
NS_ENSURE_ARG(aAddr);
|
||||
NS_ENSURE_ARG(aStream);
|
||||
|
||||
PRNetAddr prAddr;
|
||||
PR_InitializeNetAddr(PR_IpAddrAny, 0, &prAddr);
|
||||
NetAddrToPRNetAddr(aAddr, &prAddr);
|
||||
|
||||
nsRefPtr<nsUDPOutputStream> os = new nsUDPOutputStream(this, mFD, prAddr);
|
||||
return NS_AsyncCopy(aStream, os, mSts, NS_ASYNCCOPY_VIA_READSEGMENTS,
|
||||
UDP_PACKET_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsUDPSocket::SetSocketOption(const PRSocketOptionData& aOpt)
|
||||
{
|
||||
|
@ -273,7 +273,7 @@ main(int32_t argc, char *argv[])
|
||||
nsRefPtr<UDPServerListener> serverListener = new UDPServerListener();
|
||||
|
||||
// Bind server socket to 0.0.0.0
|
||||
rv = server->Init(0, false);
|
||||
rv = server->Init(0, false, true, 0);
|
||||
NS_ENSURE_SUCCESS(rv, -1);
|
||||
int32_t serverPort;
|
||||
server->GetPort(&serverPort);
|
||||
@ -281,7 +281,7 @@ main(int32_t argc, char *argv[])
|
||||
|
||||
// Bind clinet on arbitrary port
|
||||
nsRefPtr<UDPClientListener> clientListener = new UDPClientListener();
|
||||
client->Init(0, false);
|
||||
client->Init(0, false, true, 0);
|
||||
client->AsyncListen(clientListener);
|
||||
|
||||
// Write data to server
|
||||
|
@ -1,31 +0,0 @@
|
||||
var rawData = new Uint8Array([65,66,67,68]);
|
||||
var data = String.fromCharCode.apply(null, rawData);
|
||||
|
||||
function UDPSocketListener(){}
|
||||
|
||||
UDPSocketListener.prototype = {
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIUDPSocketListener]),
|
||||
|
||||
onPacketReceived : function(aSocket, aMessage){
|
||||
var mData = String.fromCharCode.apply(null, aMessage.rawData);
|
||||
do_check_eq(mData, data);
|
||||
do_check_eq(mData, aMessage.data);
|
||||
do_test_finished();
|
||||
},
|
||||
|
||||
onStopListening: function(aSocket, aStatus){}
|
||||
};
|
||||
|
||||
|
||||
function run_test(){
|
||||
var socket = Cc["@mozilla.org/network/udp-socket;1"].createInstance(Ci.nsIUDPSocket);
|
||||
|
||||
socket.init(-1, true);
|
||||
do_print("Port assigned : " + socket.port);
|
||||
socket.asyncListen(new UDPSocketListener());
|
||||
|
||||
var written = socket.send("127.0.0.1", socket.port, rawData, rawData.length);
|
||||
do_check_eq(written, data.length);
|
||||
do_test_pending();
|
||||
}
|
||||
|
61
netwerk/test/unit/test_udpsocket.js
Normal file
61
netwerk/test/unit/test_udpsocket.js
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- Mode: Javasript; indent-tab-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
const HELLO_WORLD = "Hello World";
|
||||
|
||||
add_test(function test_udp_message_raw_data() {
|
||||
do_print("test for nsIUDPMessage.rawData");
|
||||
|
||||
let socket = Cc["@mozilla.org/network/udp-socket;1"].createInstance(Ci.nsIUDPSocket);
|
||||
|
||||
socket.init(-1, true);
|
||||
do_print("Port assigned : " + socket.port);
|
||||
socket.asyncListen({
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIUDPSocketListener]),
|
||||
onPacketReceived : function(aSocket, aMessage){
|
||||
let recv_data = String.fromCharCode.apply(null, aMessage.rawData);
|
||||
do_check_eq(recv_data, HELLO_WORLD);
|
||||
do_check_eq(recv_data, aMessage.data);
|
||||
socket.close();
|
||||
run_next_test();
|
||||
},
|
||||
onStopListening: function(aSocket, aStatus){}
|
||||
});
|
||||
|
||||
let rawData = new Uint8Array(HELLO_WORLD.length);
|
||||
for (let i = 0; i < HELLO_WORLD.length; i++) {
|
||||
rawData[i] = HELLO_WORLD.charCodeAt(i);
|
||||
}
|
||||
let written = socket.send("127.0.0.1", socket.port, rawData, rawData.length);
|
||||
do_check_eq(written, HELLO_WORLD.length);
|
||||
});
|
||||
|
||||
add_test(function test_udp_send_stream() {
|
||||
do_print("test for nsIUDPSocket.sendBinaryStream");
|
||||
|
||||
let socket = Cc["@mozilla.org/network/udp-socket;1"].createInstance(Ci.nsIUDPSocket);
|
||||
|
||||
socket.init(-1, true);
|
||||
socket.asyncListen({
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIUDPSocketListener]),
|
||||
onPacketReceived : function(aSocket, aMessage){
|
||||
let recv_data = String.fromCharCode.apply(null, aMessage.rawData);
|
||||
do_check_eq(recv_data, HELLO_WORLD);
|
||||
socket.close();
|
||||
run_next_test();
|
||||
},
|
||||
onStopListening: function(aSocket, aStatus){}
|
||||
});
|
||||
|
||||
let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
|
||||
stream.setData(HELLO_WORLD, HELLO_WORLD.length);
|
||||
socket.sendBinaryStream("127.0.0.1", socket.port, stream);
|
||||
});
|
||||
|
||||
function run_test(){
|
||||
run_next_test();
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ skip-if = os == "android"
|
||||
# Allocating 4GB might actually succeed on 64 bit machines
|
||||
skip-if = bits != 32
|
||||
[test_bug935499.js]
|
||||
[test_bug952927.js]
|
||||
[test_udpsocket.js]
|
||||
[test_doomentry.js]
|
||||
[test_cacheflags.js]
|
||||
[test_cache_jar.js]
|
||||
|
Loading…
Reference in New Issue
Block a user