michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "stdio.h" michael@0: #include "TestCommon.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIComponentRegistrar.h" michael@0: #include "nspr.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsISocketTransportService.h" michael@0: #include "nsISocketTransport.h" michael@0: #include "nsIOutputStream.h" michael@0: #include "nsIInputStream.h" michael@0: michael@0: #define UDP_PORT 9050 michael@0: michael@0: #define UDP_ASSERT(condition, message) \ michael@0: PR_BEGIN_MACRO \ michael@0: NS_ASSERTION(condition, message); \ michael@0: if (!(condition)) { \ michael@0: returnCode = -1; \ michael@0: break; \ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: #define UDP_ASSERT_PRSTATUS(message) \ michael@0: PR_BEGIN_MACRO \ michael@0: NS_ASSERTION(status == PR_SUCCESS, message); \ michael@0: if (status != PR_SUCCESS) { \ michael@0: PRErrorCode err = PR_GetError(); \ michael@0: fprintf(stderr, \ michael@0: "FAIL nspr: %s: (%08x) %s\n", \ michael@0: message, \ michael@0: err, \ michael@0: PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); \ michael@0: returnCode = -1; \ michael@0: break; \ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: #define UDP_ASSERT_NSRESULT(message) \ michael@0: PR_BEGIN_MACRO \ michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), message); \ michael@0: if (NS_FAILED(rv)) { \ michael@0: fprintf(stderr, "FAIL UDPSocket: %s: %08x\n", \ michael@0: message, rv); \ michael@0: returnCode = -1; \ michael@0: break; \ michael@0: } \ michael@0: PR_END_MACRO michael@0: michael@0: int michael@0: main(int argc, char* argv[]) michael@0: { michael@0: if (test_common_init(&argc, &argv) != 0) michael@0: return -1; michael@0: michael@0: int returnCode = 0; michael@0: nsresult rv = NS_OK; michael@0: PRFileDesc *serverFD = nullptr; michael@0: michael@0: do { // act both as a scope for nsCOMPtrs to be released before XPCOM michael@0: // shutdown, as well as a easy way to abort the test michael@0: PRStatus status = PR_SUCCESS; michael@0: michael@0: nsCOMPtr servMan; michael@0: NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); michael@0: nsCOMPtr registrar = do_QueryInterface(servMan); michael@0: UDP_ASSERT(registrar, "Null nsIComponentRegistrar"); michael@0: if (registrar) michael@0: registrar->AutoRegister(nullptr); michael@0: michael@0: // listen for a incoming UDP connection on localhost michael@0: serverFD = PR_OpenUDPSocket(PR_AF_INET); michael@0: UDP_ASSERT(serverFD, "Cannot open UDP socket for listening"); michael@0: michael@0: PRSocketOptionData socketOptions; michael@0: socketOptions.option = PR_SockOpt_Nonblocking; michael@0: socketOptions.value.non_blocking = false; michael@0: status = PR_SetSocketOption(serverFD, &socketOptions); michael@0: UDP_ASSERT_PRSTATUS("Failed to set server socket as blocking"); michael@0: michael@0: PRNetAddr addr; michael@0: status = PR_InitializeNetAddr(PR_IpAddrLoopback, UDP_PORT, &addr); michael@0: UDP_ASSERT_PRSTATUS("Failed to initialize loopback address"); michael@0: michael@0: status = PR_Bind(serverFD, &addr); michael@0: UDP_ASSERT_PRSTATUS("Failed to bind server socket"); michael@0: michael@0: // dummy IOService to get around bug 379890 michael@0: nsCOMPtr ios = michael@0: do_GetService("@mozilla.org/network/io-service;1"); michael@0: michael@0: // and have a matching UDP connection for the client michael@0: nsCOMPtr sts = michael@0: do_GetService("@mozilla.org/network/socket-transport-service;1", &rv); michael@0: UDP_ASSERT_NSRESULT("Cannot get socket transport service"); michael@0: michael@0: nsCOMPtr transport; michael@0: const char *protocol = "udp"; michael@0: rv = sts->CreateTransport(&protocol, 1, NS_LITERAL_CSTRING("localhost"), michael@0: UDP_PORT, nullptr, getter_AddRefs(transport)); michael@0: UDP_ASSERT_NSRESULT("Cannot create transport"); michael@0: michael@0: uint32_t count, read; michael@0: const uint32_t data = 0xFF0056A9; michael@0: michael@0: // write to the output stream michael@0: nsCOMPtr outstream; michael@0: rv = transport->OpenOutputStream(nsITransport::OPEN_BLOCKING, michael@0: 0, 0, getter_AddRefs(outstream)); michael@0: UDP_ASSERT_NSRESULT("Cannot open output stream"); michael@0: michael@0: rv = outstream->Write((const char*)&data, sizeof(uint32_t), &count); michael@0: UDP_ASSERT_NSRESULT("Cannot write to output stream"); michael@0: UDP_ASSERT(count == sizeof(uint32_t), michael@0: "Did not write enough bytes to output stream"); michael@0: michael@0: // read from NSPR to check it's the same michael@0: count = PR_RecvFrom(serverFD, &read, sizeof(uint32_t), 0, &addr, 1); michael@0: UDP_ASSERT(count == sizeof(uint32_t), michael@0: "Did not read enough bytes from NSPR"); michael@0: status = (read == data ? PR_SUCCESS : PR_FAILURE); michael@0: UDP_ASSERT_PRSTATUS("Did not read expected data from NSPR"); michael@0: michael@0: // write to NSPR michael@0: count = PR_SendTo(serverFD, &data, sizeof(uint32_t), 0, &addr, 1); michael@0: status = (count == sizeof(uint32_t) ? PR_SUCCESS : PR_FAILURE); michael@0: UDP_ASSERT_PRSTATUS("Did not write enough bytes to NSPR"); michael@0: michael@0: // read from stream michael@0: nsCOMPtr instream; michael@0: rv = transport->OpenInputStream(nsITransport::OPEN_BLOCKING, michael@0: 0, 0, getter_AddRefs(instream)); michael@0: UDP_ASSERT_NSRESULT("Cannot open input stream"); michael@0: michael@0: rv = instream->Read((char*)&read, sizeof(uint32_t), &count); michael@0: UDP_ASSERT_NSRESULT("Cannot read from input stream"); michael@0: UDP_ASSERT(count == sizeof(uint32_t), michael@0: "Did not read enough bytes from input stream"); michael@0: UDP_ASSERT(read == data, "Did not read expected data from stream"); michael@0: michael@0: } while (false); // release all XPCOM things michael@0: if (serverFD) { michael@0: PRStatus status = PR_Close(serverFD); michael@0: if (status != PR_SUCCESS) { michael@0: PRErrorCode err = PR_GetError(); michael@0: fprintf(stderr, "FAIL: Cannot close server: (%08x) %s\n", michael@0: err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); michael@0: } michael@0: } michael@0: rv = NS_ShutdownXPCOM(nullptr); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); michael@0: michael@0: return returnCode; michael@0: } michael@0: