Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / SOCK_Test_IPv6.cpp
blob1723b383a5e7acb55771394dcaa7a1839aef2779
1 // ============================================================================
2 /**
3 * @file SOCK_Test_IPv6.cpp
5 * @brief This is a test of the <ACE_SOCK_Acceptor> and
6 * <ACE_SOCK_Connector> classes.
8 * The test forks two processes or spawns two threads (depending upon
9 * the platform) and then executes client and server allowing them to
10 * connect and exchange data.
12 * @author Prashant Jain <pjain@cs.wustl.edu>
13 * Doug Schmidt <d.schmidt@vanderbilt.edu>
14 * Brian Buesker <bbuesker@qualcomm.com>
16 // ============================================================================
18 #include "test_config.h"
19 #include "ace/OS_NS_sys_select.h"
20 #include "ace/OS_NS_sys_wait.h"
21 #include "ace/Thread.h"
22 #include "ace/Thread_Manager.h"
23 #include "ace/Time_Value.h"
24 #include "ace/SOCK_Connector.h"
25 #include "ace/SOCK_Acceptor.h"
26 #include "ace/Handle_Set.h"
28 #if !defined (ACE_LACKS_FORK)
29 # include "ace/OS_NS_unistd.h"
30 #endif
32 #if defined (ACE_HAS_IPV6)
34 static const char ACE_ALPHABET[] = "abcdefghijklmnopqrstuvwxyz";
36 static void *
37 client (void *arg)
39 ACE_INET_Addr *remote_addr = (ACE_INET_Addr *) arg;
40 ACE_INET_Addr server_addr (remote_addr->get_port_number (),
41 ACE_IPV6_LOCALHOST);
43 ACE_SOCK_Stream cli_stream;
44 ACE_SOCK_Connector con;
46 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) starting non-blocking connect\n")));
47 // Initiate timed, non-blocking connection with server.
49 // Attempt a non-blocking connect to the server.
50 if (con.connect (cli_stream, server_addr,
51 (ACE_Time_Value *) &ACE_Time_Value::zero) == -1)
53 if (errno != EWOULDBLOCK)
54 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("connection failed")));
56 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) starting timed connect\n")));
58 // Check if non-blocking connection is in progress,
59 // and wait up to ACE_DEFAULT_TIMEOUT seconds for it to complete.
60 ACE_Time_Value tv (ACE_DEFAULT_TIMEOUT);
62 if (con.complete (cli_stream, &server_addr, &tv) == -1)
63 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("connection failed")), 0);
64 else
65 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) connected to %C\n"),
66 server_addr.get_host_name ()));
69 if (cli_stream.disable (ACE_NONBLOCK) == -1)
70 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("disable")));
72 // Send data to server (correctly handles "incomplete writes").
74 for (const char *c = ACE_ALPHABET; *c != '\0'; c++)
75 if (cli_stream.send_n (c, 1) == -1)
76 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n")));
78 // Explicitly close the writer-side of the connection.
79 if (cli_stream.close_writer () == -1)
80 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close_writer")));
82 char buf[1];
84 // Wait for handshake with server.
85 if (cli_stream.recv_n (buf, 1) != 1)
86 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")));
88 // Close the connection completely.
89 if (cli_stream.close () == -1)
90 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
92 return 0;
95 static void *
96 server (void *arg)
98 ACE_SOCK_Acceptor *peer_acceptor = (ACE_SOCK_Acceptor *) arg;
100 if (peer_acceptor->enable (ACE_NONBLOCK) == -1)
101 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")));
103 // Keep these objects out here to prevent excessive constructor
104 // calls...
105 ACE_SOCK_Stream new_stream;
106 ACE_INET_Addr cli_addr;
107 ACE_Handle_Set handle_set;
108 const ACE_Time_Value def_timeout (ACE_DEFAULT_TIMEOUT);
109 ACE_Time_Value tv (def_timeout);
111 char buf[BUFSIZ];
112 const char *t = ACE_ALPHABET;
114 handle_set.reset ();
115 handle_set.set_bit (peer_acceptor->get_handle ());
117 int select_width;
118 # if defined (ACE_WIN64)
119 // This arg is ignored on Windows and causes pointer truncation
120 // warnings on 64-bit compiles.
121 select_width = 0;
122 # else
123 select_width = int (peer_acceptor->get_handle ()) + 1;
124 # endif /* ACE_WIN64 */
125 int result = ACE_OS::select (select_width,
126 handle_set,
127 0, 0, &tv);
128 ACE_TEST_ASSERT (tv == def_timeout);
130 if (result == -1)
131 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("select")), 0);
132 else if (result == 0)
134 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) select timed out, shutting down\n")));
135 return 0;
138 // Create a new ACE_SOCK_Stream endpoint (note automatic restart
139 // if errno == EINTR).
141 while ((result = peer_acceptor->accept (new_stream, &cli_addr)) != -1)
143 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
144 cli_addr.get_host_name (), cli_addr.get_port_number ()));
146 // Enable non-blocking I/O.
147 if (new_stream.enable (ACE_NONBLOCK) == -1)
148 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")), 0);
150 handle_set.reset ();
151 handle_set.set_bit (new_stream.get_handle ());
153 // Read data from client (terminate on error).
154 int select_width;
155 for (ssize_t r_bytes; ;)
157 # if defined (ACE_WIN64)
158 // This arg is ignored on Windows and causes pointer truncation
159 // warnings on 64-bit compiles.
160 select_width = 0;
161 # else
162 select_width = int (new_stream.get_handle ()) + 1;
163 # endif /* ACE_WIN64 */
164 if (ACE_OS::select (select_width,
165 handle_set,
166 0, 0, 0) == -1)
167 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("select")), 0);
169 while ((r_bytes = new_stream.recv (buf, 1)) > 0)
171 ACE_TEST_ASSERT (*t == buf[0]);
172 t++;
175 if (r_bytes == 0)
177 ACE_DEBUG ((LM_DEBUG,
178 ACE_TEXT ("(%P|%t) reached end of input, connection closed by client\n")));
180 // Handshake back with client.
181 if (new_stream.send_n ("", 1) != 1)
182 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n")));
184 // Close endpoint.
185 if (new_stream.close () == -1)
186 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
187 return 0;
189 else if (r_bytes == -1)
191 if (errno == EAGAIN || errno == EWOULDBLOCK)
192 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) no input available, going back to reading\n")));
193 else
194 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")), 0);
199 if (result == -1)
201 if (errno == EWOULDBLOCK)
202 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) no connections available, shutting down\n")));
203 else
204 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("accept")));
207 return 0;
210 static void
211 spawn ()
213 // Acceptor
214 ACE_SOCK_Acceptor peer_acceptor;
216 // Create a server address.
217 ACE_INET_Addr server_addr;
219 // Bind listener to any port and then find out what the port was.
220 if (peer_acceptor.open (ACE_Addr::sap_any, 0, AF_INET6) == -1
221 || peer_acceptor.get_local_addr (server_addr) == -1)
222 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("open")));
223 else
225 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) starting server at port %d\n"),
226 server_addr.get_port_number ()));
228 #if !defined (ACE_LACKS_FORK)
229 switch (ACE_OS::fork (ACE_TEXT("child")))
231 case -1:
232 ACE_ERROR ((LM_ERROR,
233 ACE_TEXT ("(%P|%t) %p\n%a"),
234 ACE_TEXT ("fork failed"),
235 1));
236 /* NOTREACHED */
237 case 0:
238 client (&server_addr);
239 ACE_OS::exit (0);
240 /* NOTREACHED */
241 default:
242 server ((void *) &peer_acceptor);
243 ACE_OS::wait ();
245 #elif defined (ACE_HAS_THREADS)
246 if (ACE_Thread_Manager::instance ()->spawn
247 (ACE_THR_FUNC (server),
248 (void *) &peer_acceptor,
249 THR_NEW_LWP | THR_DETACHED) == -1)
250 ACE_ERROR ((LM_ERROR,
251 ACE_TEXT ("(%P|%t) %p\n%a"),
252 ACE_TEXT ("thread create failed"),
253 1));
255 if (ACE_Thread_Manager::instance ()->spawn
256 (ACE_THR_FUNC (client),
257 (void *) &server_addr,
258 THR_NEW_LWP | THR_DETACHED) == -1)
259 ACE_ERROR ((LM_ERROR,
260 ACE_TEXT ("(%P|%t) %p\n%a"),
261 ACE_TEXT ("thread create failed"),
262 1));
264 // Wait for the threads to exit.
265 ACE_Thread_Manager::instance ()->wait ();
266 #else
267 ACE_ERROR ((LM_INFO,
268 ACE_TEXT ("(%P|%t) ")
269 ACE_TEXT ("only one thread may be run ")
270 ACE_TEXT ("in a process on this platform\n")));
271 #endif /* ACE_HAS_THREADS */
273 peer_acceptor.close ();
276 #endif /*ACE_HAS_IPV6*/
279 run_main (int, ACE_TCHAR *[])
281 ACE_START_TEST (ACE_TEXT ("SOCK_Test_IPv6"));
283 #if defined (ACE_HAS_IPV6)
284 spawn ();
285 #endif /* ACE_HAS_IPV6 */
287 ACE_END_TEST;
288 return 0;