From 945e19842317cf660d882cc5b439cfb39150d3a7 Mon Sep 17 00:00:00 2001 From: "timeless@mozdev.org" Date: Wed, 30 May 2007 23:07:26 -0700 Subject: [PATCH] Bug 191187 Request for UDP/IP (datagram) socket provider and supportbased on dougt's workpatch by mook.moz+mozbz@gmail.comr=biesi sr=bz --- netwerk/build/nsNetCID.h | 8 + netwerk/build/nsNetModule.cpp | 9 + netwerk/socket/base/Makefile.in | 1 + netwerk/socket/base/nsUDPSocketProvider.cpp | 80 ++++++++ netwerk/socket/base/nsUDPSocketProvider.h | 54 ++++++ netwerk/test/Makefile.in | 1 + netwerk/test/TestUDPSocketProvider.cpp | 191 ++++++++++++++++++++ 7 files changed, 344 insertions(+) create mode 100644 netwerk/socket/base/nsUDPSocketProvider.cpp create mode 100644 netwerk/socket/base/nsUDPSocketProvider.h create mode 100644 netwerk/test/TestUDPSocketProvider.cpp diff --git a/netwerk/build/nsNetCID.h b/netwerk/build/nsNetCID.h index 40c00d93510d..3a00ce90305d 100644 --- a/netwerk/build/nsNetCID.h +++ b/netwerk/build/nsNetCID.h @@ -713,6 +713,14 @@ { 0xa2, 0x8a, 0x5b, 0xa2, 0x44, 0x7f, 0xba, 0xce } \ } +#define NS_UDPSOCKETPROVIDER_CID \ +{ /* 320706D2-2E81-42c6-89C3-8D83B17D3FB4 */ \ + 0x320706d2, \ + 0x2e81, \ + 0x42c6, \ + { 0x89, 0xc3, 0x8d, 0x83, 0xb1, 0x7d, 0x3f, 0xb4 } \ +} + #define NS_SSLSOCKETPROVIDER_CONTRACTID \ NS_NETWORK_SOCKET_CONTRACTID_PREFIX "ssl" diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index be86a56dc3fa..195184fdc81d 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -90,6 +90,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSocketTransportService, Init) #include "nsServerSocket.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsServerSocket) +#include "nsUDPSocketProvider.h" +NS_GENERIC_FACTORY_CONSTRUCTOR(nsUDPSocketProvider) + #include "nsAsyncStreamCopier.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsAsyncStreamCopier) @@ -1024,6 +1027,12 @@ static const nsModuleComponentInfo gNetModuleInfo[] = { nsSOCKSSocketProvider::CreateV4 }, + { "nsUDPSocketProvider", + NS_UDPSOCKETPROVIDER_CID, + NS_NETWORK_SOCKET_CONTRACTID_PREFIX "udp", + nsUDPSocketProviderConstructor + }, + { NS_CACHESERVICE_CLASSNAME, NS_CACHESERVICE_CID, NS_CACHESERVICE_CONTRACTID, diff --git a/netwerk/socket/base/Makefile.in b/netwerk/socket/base/Makefile.in index 830281956075..f4e0c8e736aa 100755 --- a/netwerk/socket/base/Makefile.in +++ b/netwerk/socket/base/Makefile.in @@ -56,6 +56,7 @@ CPPSRCS = \ nsSocketProviderService.cpp \ nsSOCKSSocketProvider.cpp \ nsSOCKSIOLayer.cpp \ + nsUDPSocketProvider.cpp \ $(NULL) XPIDLSRCS = \ diff --git a/netwerk/socket/base/nsUDPSocketProvider.cpp b/netwerk/socket/base/nsUDPSocketProvider.cpp new file mode 100644 index 000000000000..723cebda99ec --- /dev/null +++ b/netwerk/socket/base/nsUDPSocketProvider.cpp @@ -0,0 +1,80 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsUDPSocketProvider.h" + +#include "nspr.h" + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsUDPSocketProvider, nsISocketProvider) + +nsUDPSocketProvider::~nsUDPSocketProvider() +{ +} + +NS_IMETHODIMP +nsUDPSocketProvider::NewSocket(PRInt32 aFamily, + const char *aHost, + PRInt32 aPort, + const char *aProxyHost, + PRInt32 aProxyPort, + PRUint32 aFlags, + PRFileDesc * *aFileDesc, + nsISupports **aSecurityInfo) +{ + NS_ENSURE_ARG_POINTER(aFileDesc); + + PRFileDesc* udpFD = PR_OpenUDPSocket(aFamily); + if (!udpFD) + return NS_ERROR_FAILURE; + + *aFileDesc = udpFD; + return NS_OK; +} + +NS_IMETHODIMP +nsUDPSocketProvider::AddToSocket(PRInt32 aFamily, + const char *aHost, + PRInt32 aPort, + const char *aProxyHost, + PRInt32 aProxyPort, + PRUint32 aFlags, + struct PRFileDesc * aFileDesc, + nsISupports **aSecurityInfo) +{ + // does not make sense to strap a UDP socket onto an existing socket + NS_NOTREACHED("Cannot layer UDP socket on an existing socket"); + return NS_ERROR_UNEXPECTED; +} diff --git a/netwerk/socket/base/nsUDPSocketProvider.h b/netwerk/socket/base/nsUDPSocketProvider.h new file mode 100644 index 000000000000..f80c4b06aa16 --- /dev/null +++ b/netwerk/socket/base/nsUDPSocketProvider.h @@ -0,0 +1,54 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsUDPSocketProvider_h__ +#define nsUDPSocketProvider_h__ + +#include "nsISocketProvider.h" + +class nsUDPSocketProvider : public nsISocketProvider +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISOCKETPROVIDER + +private: + ~nsUDPSocketProvider(); + +}; + +#endif /* nsUDPSocketProvider_h__ */ + diff --git a/netwerk/test/Makefile.in b/netwerk/test/Makefile.in index 64cd17050576..f19e5dfc5921 100644 --- a/netwerk/test/Makefile.in +++ b/netwerk/test/Makefile.in @@ -83,6 +83,7 @@ CPPSRCS += \ TestStreamPump.cpp \ TestProtocols.cpp \ TestIOThreads.cpp \ + TestUDPSocketProvider.cpp \ $(NULL) endif diff --git a/netwerk/test/TestUDPSocketProvider.cpp b/netwerk/test/TestUDPSocketProvider.cpp new file mode 100644 index 000000000000..816e11dd8422 --- /dev/null +++ b/netwerk/test/TestUDPSocketProvider.cpp @@ -0,0 +1,191 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is UDP Socket Provider unit test. + * + * The Initial Developer of the Original Code is + * Mook . + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "stdio.h" +#include "TestCommon.h" +#include "nsCOMPtr.h" +#include "nsIServiceManager.h" +#include "nsIComponentRegistrar.h" +#include "nspr.h" +#include "nsServiceManagerUtils.h" +#include "nsISocketTransportService.h" +#include "nsISocketTransport.h" +#include "nsIOutputStream.h" +#include "nsIInputStream.h" + +#define UDP_PORT 9050 + +#define UDP_ASSERT(condition, message) \ + PR_BEGIN_MACRO \ + NS_ASSERTION(condition, message); \ + if (!(condition)) { \ + returnCode = -1; \ + break; \ + } \ + PR_END_MACRO + +#define UDP_ASSERT_PRSTATUS(message) \ + PR_BEGIN_MACRO \ + NS_ASSERTION(status == PR_SUCCESS, message); \ + if (status != PR_SUCCESS) { \ + PRErrorCode err = PR_GetError(); \ + fprintf(stderr, \ + "FAIL nspr: %s: (%08x) %s\n", \ + message, \ + err, \ + PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); \ + returnCode = -1; \ + break; \ + } \ + PR_END_MACRO + +#define UDP_ASSERT_NSRESULT(message) \ + PR_BEGIN_MACRO \ + NS_ASSERTION(NS_SUCCEEDED(rv), message); \ + if (NS_FAILED(rv)) { \ + fprintf(stderr, "FAIL UDPSocket: %s: %08x\n", \ + message, rv); \ + returnCode = -1; \ + break; \ + } \ + PR_END_MACRO + +int +main(int argc, char* argv[]) +{ + if (test_common_init(&argc, &argv) != 0) + return -1; + + int returnCode = 0; + nsresult rv = NS_OK; + PRFileDesc *serverFD = nsnull; + + do { // act both as a scope for nsCOMPtrs to be released before XPCOM + // shutdown, as well as a easy way to abort the test + PRStatus status = PR_SUCCESS; + + nsCOMPtr servMan; + NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull); + nsCOMPtr registrar = do_QueryInterface(servMan); + UDP_ASSERT(registrar, "Null nsIComponentRegistrar"); + if (registrar) + registrar->AutoRegister(nsnull); + + // listen for a incoming UDP connection on localhost + serverFD = PR_OpenUDPSocket(PR_AF_INET); + UDP_ASSERT(serverFD, "Cannot open UDP socket for listening"); + + PRSocketOptionData socketOptions; + socketOptions.option = PR_SockOpt_Nonblocking; + socketOptions.value.non_blocking = PR_FALSE; + status = PR_SetSocketOption(serverFD, &socketOptions); + UDP_ASSERT_PRSTATUS("Failed to set server socket as blocking"); + + PRNetAddr addr; + status = PR_InitializeNetAddr(PR_IpAddrLoopback, UDP_PORT, &addr); + UDP_ASSERT_PRSTATUS("Failed to initialize loopback address"); + + status = PR_Bind(serverFD, &addr); + UDP_ASSERT_PRSTATUS("Failed to bind server socket"); + + // dummy IOService to get around bug 379890 + nsCOMPtr ios = + do_GetService("@mozilla.org/network/io-service;1"); + + // and have a matching UDP connection for the client + nsCOMPtr sts = + do_GetService("@mozilla.org/network/socket-transport-service;1", &rv); + UDP_ASSERT_NSRESULT("Cannot get socket transport service"); + + nsCOMPtr transport; + const char *protocol = "udp"; + rv = sts->CreateTransport(&protocol, 1, NS_LITERAL_CSTRING("localhost"), + UDP_PORT, nsnull, getter_AddRefs(transport)); + UDP_ASSERT_NSRESULT("Cannot create transport"); + + PRUint32 count, read; + const PRUint32 data = 0xFF0056A9; + + // write to the output stream + nsCOMPtr outstream; + rv = transport->OpenOutputStream(nsITransport::OPEN_BLOCKING, + 0, 0, getter_AddRefs(outstream)); + UDP_ASSERT_NSRESULT("Cannot open output stream"); + + rv = outstream->Write((const char*)&data, sizeof(PRUint32), &count); + UDP_ASSERT_NSRESULT("Cannot write to output stream"); + UDP_ASSERT(count == sizeof(PRUint32), + "Did not write enough bytes to output stream"); + + // read from NSPR to check it's the same + count = PR_RecvFrom(serverFD, &read, sizeof(PRUint32), 0, &addr, 1); + UDP_ASSERT(count == sizeof(PRUint32), + "Did not read enough bytes from NSPR"); + status = (read == data ? PR_SUCCESS : PR_FAILURE); + UDP_ASSERT_PRSTATUS("Did not read expected data from NSPR"); + + // write to NSPR + count = PR_SendTo(serverFD, &data, sizeof(PRUint32), 0, &addr, 1); + status = (count == sizeof(PRUint32) ? PR_SUCCESS : PR_FAILURE); + UDP_ASSERT_PRSTATUS("Did not write enough bytes to NSPR"); + + // read from stream + nsCOMPtr instream; + rv = transport->OpenInputStream(nsITransport::OPEN_BLOCKING, + 0, 0, getter_AddRefs(instream)); + UDP_ASSERT_NSRESULT("Cannot open input stream"); + + rv = instream->Read((char*)&read, sizeof(PRUint32), &count); + UDP_ASSERT_NSRESULT("Cannot read from input stream"); + UDP_ASSERT(count == sizeof(PRUint32), + "Did not read enough bytes from input stream"); + UDP_ASSERT(read == data, "Did not read expected data from stream"); + + } while (false); // release all XPCOM things + if (serverFD) { + PRStatus status = PR_Close(serverFD); + if (status != PR_SUCCESS) { + PRErrorCode err = PR_GetError(); + fprintf(stderr, "FAIL: Cannot close server: (%08x) %s\n", + err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); + } + } + rv = NS_ShutdownXPCOM(nsnull); + NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); + + return returnCode; +} +