1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * This test is the same as acceptread.c except that it uses the
40 * emulated acceptread method instead of the regular acceptread.
55 #define DEFAULT_PORT 12273
56 #define GET "GET / HTTP/1.0\n\n"
57 static PRFileDesc
*std_out
, *err_out
;
58 static PRIntervalTime write_dally
, accept_timeout
;
59 static PRDescIdentity emu_layer_ident
;
60 static PRIOMethods emu_layer_methods
;
62 /* the acceptread method in emu_layer_methods */
63 static PRInt32 PR_CALLBACK
emu_AcceptRead(PRFileDesc
*sd
, PRFileDesc
**nd
,
64 PRNetAddr
**raddr
, void *buf
, PRInt32 amount
, PRIntervalTime timeout
)
66 return PR_EmulateAcceptRead(sd
, nd
, raddr
, buf
, amount
, timeout
);
69 static PRStatus
PrintAddress(const PRNetAddr
* address
)
72 PRStatus rv
= PR_NetAddrToString(address
, buffer
, sizeof(buffer
));
73 if (PR_FAILURE
== rv
) PL_FPrintError(err_out
, "PR_NetAddrToString");
75 std_out
, "Accepted connection from (0x%p)%s:%d\n",
76 address
, buffer
, address
->inet
.port
);
80 static void ConnectingThread(void *arg
)
85 PRNetAddr peer_addr
, *addr
;
87 addr
= (PRNetAddr
*)arg
;
89 sock
= PR_NewTCPSocket();
92 PL_FPrintError(err_out
, "PR_NewTCPSocket (client) failed");
96 if (PR_Connect(sock
, addr
, PR_INTERVAL_NO_TIMEOUT
) == PR_FAILURE
)
98 PL_FPrintError(err_out
, "PR_Connect (client) failed");
101 if (PR_GetPeerName(sock
, &peer_addr
) == PR_FAILURE
)
103 PL_FPrintError(err_out
, "PR_GetPeerName (client) failed");
108 ** Then wait between the connection coming up and sending the expected
109 ** data. At some point in time, the server should fail due to a timeou
110 ** on the AcceptRead() operation, which according to the document is
111 ** only due to the read() portion.
113 PR_Sleep(write_dally
);
115 nbytes
= PR_Send(sock
, GET
, sizeof(GET
), 0, PR_INTERVAL_NO_TIMEOUT
);
116 if (nbytes
== -1) PL_FPrintError(err_out
, "PR_Send (client) failed");
118 nbytes
= PR_Recv(sock
, buf
, sizeof(buf
), 0, PR_INTERVAL_NO_TIMEOUT
);
119 if (nbytes
== -1) PL_FPrintError(err_out
, "PR_Recv (client) failed");
122 PR_fprintf(std_out
, "PR_Recv (client) succeeded: %d bytes\n", nbytes
);
123 buf
[sizeof(buf
) - 1] = '\0';
124 PR_fprintf(std_out
, "%s\n", buf
);
127 if (PR_FAILURE
== PR_Shutdown(sock
, PR_SHUTDOWN_BOTH
))
128 PL_FPrintError(err_out
, "PR_Shutdown (client) failed");
130 if (PR_FAILURE
== PR_Close(sock
))
131 PL_FPrintError(err_out
, "PR_Close (client) failed");
134 } /* ConnectingThread */
137 static void AcceptingThread(void *arg
)
141 PRSize buf_size
= BUF_SIZE
;
142 PRUint8 buf
[BUF_SIZE
+ (2 * sizeof(PRNetAddr
)) + 32];
143 PRNetAddr
*accept_addr
, *listen_addr
= (PRNetAddr
*)arg
;
144 PRFileDesc
*accept_sock
, *listen_sock
= PR_NewTCPSocket();
146 PRSocketOptionData sock_opt
;
148 if (NULL
== listen_sock
)
150 PL_FPrintError(err_out
, "PR_NewTCPSocket (server) failed");
153 layer
= PR_CreateIOLayerStub(emu_layer_ident
, &emu_layer_methods
);
156 PL_FPrintError(err_out
, "PR_CreateIOLayerStub (server) failed");
159 if (PR_PushIOLayer(listen_sock
, PR_TOP_IO_LAYER
, layer
) == PR_FAILURE
)
161 PL_FPrintError(err_out
, "PR_PushIOLayer (server) failed");
164 sock_opt
.option
= PR_SockOpt_Reuseaddr
;
165 sock_opt
.value
.reuse_addr
= PR_TRUE
;
166 rv
= PR_SetSocketOption(listen_sock
, &sock_opt
);
167 if (PR_FAILURE
== rv
)
169 PL_FPrintError(err_out
, "PR_SetSocketOption (server) failed");
172 rv
= PR_Bind(listen_sock
, listen_addr
);
173 if (PR_FAILURE
== rv
)
175 PL_FPrintError(err_out
, "PR_Bind (server) failed");
178 rv
= PR_Listen(listen_sock
, 10);
179 if (PR_FAILURE
== rv
)
181 PL_FPrintError(err_out
, "PR_Listen (server) failed");
184 bytes
= PR_AcceptRead(
185 listen_sock
, &accept_sock
, &accept_addr
, buf
, buf_size
, accept_timeout
);
187 if (-1 == bytes
) PL_FPrintError(err_out
, "PR_AcceptRead (server) failed");
190 PrintAddress(accept_addr
);
192 std_out
, "(Server) read [0x%p..0x%p) %s\n",
193 buf
, &buf
[BUF_SIZE
], buf
);
194 bytes
= PR_Write(accept_sock
, buf
, bytes
);
195 rv
= PR_Shutdown(accept_sock
, PR_SHUTDOWN_BOTH
);
196 if (PR_FAILURE
== rv
)
197 PL_FPrintError(err_out
, "PR_Shutdown (server) failed");
202 rv
= PR_Close(accept_sock
);
203 if (PR_FAILURE
== rv
)
204 PL_FPrintError(err_out
, "PR_Close (server) failed");
207 rv
= PR_Close(listen_sock
);
208 if (PR_FAILURE
== rv
)
209 PL_FPrintError(err_out
, "PR_Close (server) failed");
210 } /* AcceptingThread */
212 PRIntn
main(PRIntn argc
, char **argv
)
217 PRUint16 port_number
;
218 char netdb_buf
[PR_NETDB_BUF_SIZE
];
219 PRNetAddr client_addr
, server_addr
;
220 PRThread
*client_thread
, *server_thread
;
221 PRIntervalTime delta
= PR_MillisecondsToInterval(500);
225 accept_timeout
= PR_SecondsToInterval(2);
226 emu_layer_ident
= PR_GetUniqueIdentity("Emulated AcceptRead");
227 emu_layer_methods
= *PR_GetDefaultIOMethods();
228 emu_layer_methods
.acceptread
= emu_AcceptRead
;
230 if (argc
!= 2 && argc
!= 3) port_number
= DEFAULT_PORT
;
231 else port_number
= (PRUint16
)atoi(argv
[(argc
== 2) ? 1 : 2]);
233 status
= PR_InitializeNetAddr(PR_IpAddrAny
, port_number
, &server_addr
);
234 if (PR_SUCCESS
!= status
)
236 PL_FPrintError(err_out
, "PR_InitializeNetAddr failed");
241 status
= PR_InitializeNetAddr(
242 PR_IpAddrLoopback
, port_number
, &client_addr
);
243 if (PR_SUCCESS
!= status
)
245 PL_FPrintError(err_out
, "PR_InitializeNetAddr failed");
251 status
= PR_GetHostByName(
252 argv
[1], netdb_buf
, sizeof(netdb_buf
), &he
);
253 if (status
== PR_FAILURE
)
255 PL_FPrintError(err_out
, "PR_GetHostByName failed");
258 next_index
= PR_EnumerateHostEnt(0, &he
, port_number
, &client_addr
);
259 if (next_index
== -1)
261 PL_FPrintError(err_out
, "PR_EnumerateHostEnt failed");
268 write_dally
< accept_timeout
+ (2 * delta
);
269 write_dally
+= delta
)
272 std_out
, "Testing w/ write_dally = %d msec\n",
273 PR_IntervalToMilliseconds(write_dally
));
274 server_thread
= PR_CreateThread(
275 PR_USER_THREAD
, AcceptingThread
, &server_addr
,
276 PR_PRIORITY_NORMAL
, PR_GLOBAL_THREAD
, PR_JOINABLE_THREAD
, 0);
277 if (server_thread
== NULL
)
279 PL_FPrintError(err_out
, "PR_CreateThread (server) failed");
283 PR_Sleep(delta
); /* let the server pot thicken */
285 client_thread
= PR_CreateThread(
286 PR_USER_THREAD
, ConnectingThread
, &client_addr
,
287 PR_PRIORITY_NORMAL
, PR_GLOBAL_THREAD
, PR_JOINABLE_THREAD
, 0);
288 if (client_thread
== NULL
)
290 PL_FPrintError(err_out
, "PR_CreateThread (client) failed");
294 if (PR_JoinThread(client_thread
) == PR_FAILURE
)
295 PL_FPrintError(err_out
, "PR_JoinThread (client) failed");
297 if (PR_JoinThread(server_thread
) == PR_FAILURE
)
298 PL_FPrintError(err_out
, "PR_JoinThread (server) failed");