|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "stdio.h" |
|
6 #include "TestCommon.h" |
|
7 #include "nsCOMPtr.h" |
|
8 #include "nsIServiceManager.h" |
|
9 #include "nsIComponentRegistrar.h" |
|
10 #include "nspr.h" |
|
11 #include "nsServiceManagerUtils.h" |
|
12 #include "nsISocketTransportService.h" |
|
13 #include "nsISocketTransport.h" |
|
14 #include "nsIOutputStream.h" |
|
15 #include "nsIInputStream.h" |
|
16 |
|
17 #define UDP_PORT 9050 |
|
18 |
|
19 #define UDP_ASSERT(condition, message) \ |
|
20 PR_BEGIN_MACRO \ |
|
21 NS_ASSERTION(condition, message); \ |
|
22 if (!(condition)) { \ |
|
23 returnCode = -1; \ |
|
24 break; \ |
|
25 } \ |
|
26 PR_END_MACRO |
|
27 |
|
28 #define UDP_ASSERT_PRSTATUS(message) \ |
|
29 PR_BEGIN_MACRO \ |
|
30 NS_ASSERTION(status == PR_SUCCESS, message); \ |
|
31 if (status != PR_SUCCESS) { \ |
|
32 PRErrorCode err = PR_GetError(); \ |
|
33 fprintf(stderr, \ |
|
34 "FAIL nspr: %s: (%08x) %s\n", \ |
|
35 message, \ |
|
36 err, \ |
|
37 PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); \ |
|
38 returnCode = -1; \ |
|
39 break; \ |
|
40 } \ |
|
41 PR_END_MACRO |
|
42 |
|
43 #define UDP_ASSERT_NSRESULT(message) \ |
|
44 PR_BEGIN_MACRO \ |
|
45 NS_ASSERTION(NS_SUCCEEDED(rv), message); \ |
|
46 if (NS_FAILED(rv)) { \ |
|
47 fprintf(stderr, "FAIL UDPSocket: %s: %08x\n", \ |
|
48 message, rv); \ |
|
49 returnCode = -1; \ |
|
50 break; \ |
|
51 } \ |
|
52 PR_END_MACRO |
|
53 |
|
54 int |
|
55 main(int argc, char* argv[]) |
|
56 { |
|
57 if (test_common_init(&argc, &argv) != 0) |
|
58 return -1; |
|
59 |
|
60 int returnCode = 0; |
|
61 nsresult rv = NS_OK; |
|
62 PRFileDesc *serverFD = nullptr; |
|
63 |
|
64 do { // act both as a scope for nsCOMPtrs to be released before XPCOM |
|
65 // shutdown, as well as a easy way to abort the test |
|
66 PRStatus status = PR_SUCCESS; |
|
67 |
|
68 nsCOMPtr<nsIServiceManager> servMan; |
|
69 NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); |
|
70 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan); |
|
71 UDP_ASSERT(registrar, "Null nsIComponentRegistrar"); |
|
72 if (registrar) |
|
73 registrar->AutoRegister(nullptr); |
|
74 |
|
75 // listen for a incoming UDP connection on localhost |
|
76 serverFD = PR_OpenUDPSocket(PR_AF_INET); |
|
77 UDP_ASSERT(serverFD, "Cannot open UDP socket for listening"); |
|
78 |
|
79 PRSocketOptionData socketOptions; |
|
80 socketOptions.option = PR_SockOpt_Nonblocking; |
|
81 socketOptions.value.non_blocking = false; |
|
82 status = PR_SetSocketOption(serverFD, &socketOptions); |
|
83 UDP_ASSERT_PRSTATUS("Failed to set server socket as blocking"); |
|
84 |
|
85 PRNetAddr addr; |
|
86 status = PR_InitializeNetAddr(PR_IpAddrLoopback, UDP_PORT, &addr); |
|
87 UDP_ASSERT_PRSTATUS("Failed to initialize loopback address"); |
|
88 |
|
89 status = PR_Bind(serverFD, &addr); |
|
90 UDP_ASSERT_PRSTATUS("Failed to bind server socket"); |
|
91 |
|
92 // dummy IOService to get around bug 379890 |
|
93 nsCOMPtr<nsISupports> ios = |
|
94 do_GetService("@mozilla.org/network/io-service;1"); |
|
95 |
|
96 // and have a matching UDP connection for the client |
|
97 nsCOMPtr<nsISocketTransportService> sts = |
|
98 do_GetService("@mozilla.org/network/socket-transport-service;1", &rv); |
|
99 UDP_ASSERT_NSRESULT("Cannot get socket transport service"); |
|
100 |
|
101 nsCOMPtr<nsISocketTransport> transport; |
|
102 const char *protocol = "udp"; |
|
103 rv = sts->CreateTransport(&protocol, 1, NS_LITERAL_CSTRING("localhost"), |
|
104 UDP_PORT, nullptr, getter_AddRefs(transport)); |
|
105 UDP_ASSERT_NSRESULT("Cannot create transport"); |
|
106 |
|
107 uint32_t count, read; |
|
108 const uint32_t data = 0xFF0056A9; |
|
109 |
|
110 // write to the output stream |
|
111 nsCOMPtr<nsIOutputStream> outstream; |
|
112 rv = transport->OpenOutputStream(nsITransport::OPEN_BLOCKING, |
|
113 0, 0, getter_AddRefs(outstream)); |
|
114 UDP_ASSERT_NSRESULT("Cannot open output stream"); |
|
115 |
|
116 rv = outstream->Write((const char*)&data, sizeof(uint32_t), &count); |
|
117 UDP_ASSERT_NSRESULT("Cannot write to output stream"); |
|
118 UDP_ASSERT(count == sizeof(uint32_t), |
|
119 "Did not write enough bytes to output stream"); |
|
120 |
|
121 // read from NSPR to check it's the same |
|
122 count = PR_RecvFrom(serverFD, &read, sizeof(uint32_t), 0, &addr, 1); |
|
123 UDP_ASSERT(count == sizeof(uint32_t), |
|
124 "Did not read enough bytes from NSPR"); |
|
125 status = (read == data ? PR_SUCCESS : PR_FAILURE); |
|
126 UDP_ASSERT_PRSTATUS("Did not read expected data from NSPR"); |
|
127 |
|
128 // write to NSPR |
|
129 count = PR_SendTo(serverFD, &data, sizeof(uint32_t), 0, &addr, 1); |
|
130 status = (count == sizeof(uint32_t) ? PR_SUCCESS : PR_FAILURE); |
|
131 UDP_ASSERT_PRSTATUS("Did not write enough bytes to NSPR"); |
|
132 |
|
133 // read from stream |
|
134 nsCOMPtr<nsIInputStream> instream; |
|
135 rv = transport->OpenInputStream(nsITransport::OPEN_BLOCKING, |
|
136 0, 0, getter_AddRefs(instream)); |
|
137 UDP_ASSERT_NSRESULT("Cannot open input stream"); |
|
138 |
|
139 rv = instream->Read((char*)&read, sizeof(uint32_t), &count); |
|
140 UDP_ASSERT_NSRESULT("Cannot read from input stream"); |
|
141 UDP_ASSERT(count == sizeof(uint32_t), |
|
142 "Did not read enough bytes from input stream"); |
|
143 UDP_ASSERT(read == data, "Did not read expected data from stream"); |
|
144 |
|
145 } while (false); // release all XPCOM things |
|
146 if (serverFD) { |
|
147 PRStatus status = PR_Close(serverFD); |
|
148 if (status != PR_SUCCESS) { |
|
149 PRErrorCode err = PR_GetError(); |
|
150 fprintf(stderr, "FAIL: Cannot close server: (%08x) %s\n", |
|
151 err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); |
|
152 } |
|
153 } |
|
154 rv = NS_ShutdownXPCOM(nullptr); |
|
155 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); |
|
156 |
|
157 return returnCode; |
|
158 } |
|
159 |