1 // ============================================================================
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"
32 #if defined (ACE_HAS_IPV6)
34 static const char ACE_ALPHABET
[] = "abcdefghijklmnopqrstuvwxyz";
39 ACE_INET_Addr
*remote_addr
= (ACE_INET_Addr
*) arg
;
40 ACE_INET_Addr
server_addr (remote_addr
->get_port_number (),
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);
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")));
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")));
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
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
);
112 const char *t
= ACE_ALPHABET
;
115 handle_set
.set_bit (peer_acceptor
->get_handle ());
118 # if defined (ACE_WIN64)
119 // This arg is ignored on Windows and causes pointer truncation
120 // warnings on 64-bit compiles.
123 select_width
= int (peer_acceptor
->get_handle ()) + 1;
124 # endif /* ACE_WIN64 */
125 int result
= ACE_OS::select (select_width
,
128 ACE_TEST_ASSERT (tv
== def_timeout
);
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")));
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);
151 handle_set
.set_bit (new_stream
.get_handle ());
153 // Read data from client (terminate on error).
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.
162 select_width
= int (new_stream
.get_handle ()) + 1;
163 # endif /* ACE_WIN64 */
164 if (ACE_OS::select (select_width
,
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]);
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")));
185 if (new_stream
.close () == -1)
186 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
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")));
194 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")), 0);
201 if (errno
== EWOULDBLOCK
)
202 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) no connections available, shutting down\n")));
204 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("accept")));
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")));
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")))
232 ACE_ERROR ((LM_ERROR
,
233 ACE_TEXT ("(%P|%t) %p\n%a"),
234 ACE_TEXT ("fork failed"),
238 client (&server_addr
);
242 server ((void *) &peer_acceptor
);
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"),
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"),
264 // Wait for the threads to exit.
265 ACE_Thread_Manager::instance ()->wait ();
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)
285 #endif /* ACE_HAS_IPV6 */