2 //=============================================================================
6 * This is a test of the <ACE_SOCK_Acceptor> and
7 * <ACE_SOCK_Connector> classes. The test forks two processes or
8 * spawns two threads (depending upon the platform) and then
9 * executes client and server allowing them to connect and
12 * @author Prashant Jain <pjain@cs.wustl.edu> and Doug Schmidt <d.schmidt@vanderbilt.edu>
14 //=============================================================================
17 #include "test_config.h"
18 #include "ace/OS_NS_unistd.h"
19 #include "ace/OS_NS_sys_wait.h"
20 #include "ace/Thread.h"
21 #include "ace/Time_Value.h"
22 #include "ace/Thread_Manager.h"
23 #include "ace/SOCK_Connector.h"
24 #include "ace/SOCK_Acceptor.h"
25 #include "ace/Handle_Set.h"
29 static const char ACE_ALPHABET
[] = "abcdefghijklmnopqrstuvwxyz";
34 ACE_INET_Addr
*remote_addr
= (ACE_INET_Addr
*) arg
;
35 ACE_INET_Addr
server_addr (remote_addr
->get_port_number (), ACE_LOCALHOST
);
36 ACE_SOCK_Stream cli_stream
;
37 ACE_SOCK_Connector con
;
39 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) starting non-blocking connect\n")));
40 // Initiate timed, non-blocking connection with server.
42 // Attempt a non-blocking connect to the server.
43 if (con
.connect (cli_stream
, server_addr
,
44 (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
46 if (errno
!= EWOULDBLOCK
)
47 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("connection failed")));
49 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) starting timed connect\n")));
51 // Check if non-blocking connection is in progress,
52 // and wait up to ACE_DEFAULT_TIMEOUT seconds for it to complete.
53 ACE_Time_Value
tv (ACE_DEFAULT_TIMEOUT
);
55 if (con
.complete (cli_stream
, &server_addr
, &tv
) == -1)
56 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("connection failed")), 0);
58 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) connected to %C\n"),
59 server_addr
.get_host_name ()));
62 if (cli_stream
.disable (ACE_NONBLOCK
) == -1)
63 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("disable")));
66 const ACE_Time_Value
def_timeout (ACE_DEFAULT_TIMEOUT
);
67 ACE_Time_Value
tv (def_timeout
);
68 int result
= ACE::handle_ready (cli_stream
.get_handle (), &tv
,
72 // we expect the handle to be at least write_ready since it is freshly connected.
74 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("ACE::handle_ready")), 0);
76 // Send data to server (correctly handles "incomplete writes").
77 for (const char *c
= ACE_ALPHABET
; *c
!= '\0'; c
++)
78 if (cli_stream
.send_n (c
, 1) == -1)
79 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n")));
81 // Explicitly close the writer-side of the connection.
82 if (cli_stream
.close_writer () == -1)
83 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close_writer")));
87 // Wait for handshake with server.
88 if (cli_stream
.recv_n (buf
, 1) != 1)
89 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")));
91 // Close the connection completely.
92 if (cli_stream
.close () == -1)
93 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
101 ACE_SOCK_Acceptor
*peer_acceptor
= (ACE_SOCK_Acceptor
*) arg
;
103 if (peer_acceptor
->enable (ACE_NONBLOCK
) == -1)
104 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")));
106 // Keep these objects out here to prevent excessive constructor
108 ACE_SOCK_Stream new_stream
;
109 ACE_INET_Addr cli_addr
;
110 const ACE_Time_Value
def_timeout (ACE_DEFAULT_TIMEOUT
);
111 ACE_Time_Value
tv (def_timeout
);
114 const char *t
= ACE_ALPHABET
;
116 int result
= ACE::handle_read_ready (peer_acceptor
->get_handle (), &tv
);
118 ACE_TEST_ASSERT (tv
== def_timeout
);
121 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("handle_read_ready")), 0);
123 // Create a new ACE_SOCK_Stream endpoint (note automatic restart
124 // if errno == EINTR).
126 while ((result
= peer_acceptor
->accept (new_stream
, &cli_addr
)) != -1)
128 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
129 cli_addr
.get_host_name (), cli_addr
.get_port_number ()));
131 // Enable non-blocking I/O.
132 if (new_stream
.enable (ACE_NONBLOCK
) == -1)
133 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")), 0);
135 // Read data from client (terminate on error).
136 for (ssize_t r_bytes
; ;)
138 if (ACE::handle_read_ready (new_stream
.get_handle (), 0) == -1)
139 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("handle_read_ready")), 0);
141 while ((r_bytes
= new_stream
.recv (buf
, 1)) > 0)
143 ACE_TEST_ASSERT (*t
== buf
[0]);
149 ACE_DEBUG ((LM_DEBUG
,
150 ACE_TEXT ("(%P|%t) reached end of input, connection closed by client\n")));
152 // Handshake back with client.
153 if (new_stream
.send_n ("", 1) != 1)
154 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n")));
157 if (new_stream
.close () == -1)
158 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
161 else if (r_bytes
== -1)
163 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
)
164 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) no input available, going back to reading\n")));
166 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")), 0);
173 if (errno
== EWOULDBLOCK
)
174 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) no connections available, shutting down\n")));
176 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("accept")));
186 ACE_SOCK_Acceptor peer_acceptor
;
188 // Create a server address.
189 ACE_INET_Addr server_addr
;
191 // Bind listener to any port and then find out what the port was.
192 if (peer_acceptor
.open (ACE_Addr::sap_any
) == -1
193 || peer_acceptor
.get_local_addr (server_addr
) == -1)
194 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("open")));
197 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) starting server at port %d\n"),
198 server_addr
.get_port_number ()));
200 #if !defined (ACE_LACKS_FORK)
201 switch (ACE_OS::fork (ACE_TEXT ("child")))
204 ACE_ERROR ((LM_ERROR
,
205 ACE_TEXT ("(%P|%t) %p\n%a"),
206 ACE_TEXT ("fork failed"),
210 client (&server_addr
);
214 server ((void *) &peer_acceptor
);
217 #elif defined (ACE_HAS_THREADS)
218 if (ACE_Thread_Manager::instance ()->spawn
219 (ACE_THR_FUNC (server
),
220 (void *) &peer_acceptor
,
221 THR_NEW_LWP
| THR_DETACHED
) == -1)
222 ACE_ERROR ((LM_ERROR
,
223 ACE_TEXT ("(%P|%t) %p\n%a"),
224 ACE_TEXT ("thread create failed"),
227 if (ACE_Thread_Manager::instance ()->spawn
228 (ACE_THR_FUNC (client
),
229 (void *) &server_addr
,
230 THR_NEW_LWP
| THR_DETACHED
) == -1)
231 ACE_ERROR ((LM_ERROR
,
232 ACE_TEXT ("(%P|%t) %p\n%a"),
233 ACE_TEXT ("thread create failed"),
236 // Wait for the threads to exit.
237 ACE_Thread_Manager::instance ()->wait ();
240 ACE_TEXT ("(%P|%t) ")
241 ACE_TEXT ("only one thread may be run ")
242 ACE_TEXT ("in a process on this platform\n")));
243 #endif /* ACE_HAS_THREADS */
245 peer_acceptor
.close ();
250 run_main (int, ACE_TCHAR
*[])
252 ACE_START_TEST (ACE_TEXT ("SOCK_Test"));
254 #ifndef ACE_LACKS_ACCEPT