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"
28 static const char ACE_ALPHABET
[] = "abcdefghijklmnopqrstuvwxyz";
33 ACE_INET_Addr
*remote_addr
= (ACE_INET_Addr
*) arg
;
34 ACE_INET_Addr
server_addr (remote_addr
->get_port_number (), ACE_LOCALHOST
);
35 ACE_SOCK_Stream cli_stream
;
36 ACE_SOCK_Connector con
;
38 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) starting non-blocking connect\n")));
39 // Initiate timed, non-blocking connection with server.
41 // Attempt a non-blocking connect to the server.
42 if (con
.connect (cli_stream
, server_addr
,
43 (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
45 if (errno
!= EWOULDBLOCK
)
46 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("connection failed")));
48 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) starting timed connect\n")));
50 // Check if non-blocking connection is in progress,
51 // and wait up to ACE_DEFAULT_TIMEOUT seconds for it to complete.
52 ACE_Time_Value
tv (ACE_DEFAULT_TIMEOUT
);
54 if (con
.complete (cli_stream
, &server_addr
, &tv
) == -1)
55 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("connection failed")), 0);
57 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) connected to %C\n"),
58 server_addr
.get_host_name ()));
61 if (cli_stream
.disable (ACE_NONBLOCK
) == -1)
62 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("disable")));
65 const ACE_Time_Value
def_timeout (ACE_DEFAULT_TIMEOUT
);
66 ACE_Time_Value
tv (def_timeout
);
67 int result
= ACE::handle_ready (cli_stream
.get_handle (), &tv
,
71 // we expect the handle to be at least write_ready since it is freshly connected.
73 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("ACE::handle_ready")), 0);
75 // Send data to server (correctly handles "incomplete writes").
76 for (const char *c
= ACE_ALPHABET
; *c
!= '\0'; c
++)
77 if (cli_stream
.send_n (c
, 1) == -1)
78 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n")));
80 // Explicitly close the writer-side of the connection.
81 if (cli_stream
.close_writer () == -1)
82 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close_writer")));
86 // Wait for handshake with server.
87 if (cli_stream
.recv_n (buf
, 1) != 1)
88 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")));
90 // Close the connection completely.
91 if (cli_stream
.close () == -1)
92 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
100 ACE_SOCK_Acceptor
*peer_acceptor
= (ACE_SOCK_Acceptor
*) arg
;
102 if (peer_acceptor
->enable (ACE_NONBLOCK
) == -1)
103 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")));
105 // Keep these objects out here to prevent excessive constructor
107 ACE_SOCK_Stream new_stream
;
108 ACE_INET_Addr cli_addr
;
109 const ACE_Time_Value
def_timeout (ACE_DEFAULT_TIMEOUT
);
110 ACE_Time_Value
tv (def_timeout
);
113 const char *t
= ACE_ALPHABET
;
115 int result
= ACE::handle_read_ready (peer_acceptor
->get_handle (), &tv
);
117 ACE_TEST_ASSERT (tv
== def_timeout
);
120 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("handle_read_ready")), 0);
122 // Create a new ACE_SOCK_Stream endpoint (note automatic restart
123 // if errno == EINTR).
125 while ((result
= peer_acceptor
->accept (new_stream
, &cli_addr
)) != -1)
127 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
128 cli_addr
.get_host_name (), cli_addr
.get_port_number ()));
130 // Enable non-blocking I/O.
131 if (new_stream
.enable (ACE_NONBLOCK
) == -1)
132 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("enable")), 0);
134 // Read data from client (terminate on error).
135 for (ssize_t r_bytes
; ;)
137 if (ACE::handle_read_ready (new_stream
.get_handle (), 0) == -1)
138 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("handle_read_ready")), 0);
140 while ((r_bytes
= new_stream
.recv (buf
, 1)) > 0)
142 ACE_TEST_ASSERT (*t
== buf
[0]);
148 ACE_DEBUG ((LM_DEBUG
,
149 ACE_TEXT ("(%P|%t) reached end of input, connection closed by client\n")));
151 // Handshake back with client.
152 if (new_stream
.send_n ("", 1) != 1)
153 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("send_n")));
156 if (new_stream
.close () == -1)
157 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
160 else if (r_bytes
== -1)
162 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
)
163 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) no input available, going back to reading\n")));
165 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")), 0);
172 if (errno
== EWOULDBLOCK
)
173 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) no connections available, shutting down\n")));
175 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("accept")));
185 ACE_SOCK_Acceptor peer_acceptor
;
187 // Create a server address.
188 ACE_INET_Addr server_addr
;
190 // Bind listener to any port and then find out what the port was.
191 if (peer_acceptor
.open (ACE_Addr::sap_any
) == -1
192 || peer_acceptor
.get_local_addr (server_addr
) == -1)
193 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("open")));
196 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) starting server at port %d\n"),
197 server_addr
.get_port_number ()));
199 #if !defined (ACE_LACKS_FORK)
200 switch (ACE_OS::fork (ACE_TEXT ("child")))
203 ACE_ERROR ((LM_ERROR
,
204 ACE_TEXT ("(%P|%t) %p\n"),
205 ACE_TEXT ("fork failed"),
209 client (&server_addr
);
213 server ((void *) &peer_acceptor
);
216 #elif defined (ACE_HAS_THREADS)
217 if (ACE_Thread_Manager::instance ()->spawn
218 (ACE_THR_FUNC (server
),
219 (void *) &peer_acceptor
,
220 THR_NEW_LWP
| THR_DETACHED
) == -1)
221 ACE_ERROR ((LM_ERROR
,
222 ACE_TEXT ("(%P|%t) %p\n%a"),
223 ACE_TEXT ("thread create failed"),
226 if (ACE_Thread_Manager::instance ()->spawn
227 (ACE_THR_FUNC (client
),
228 (void *) &server_addr
,
229 THR_NEW_LWP
| THR_DETACHED
) == -1)
230 ACE_ERROR ((LM_ERROR
,
231 ACE_TEXT ("(%P|%t) %p\n%a"),
232 ACE_TEXT ("thread create failed"),
235 // Wait for the threads to exit.
236 ACE_Thread_Manager::instance ()->wait ();
239 ACE_TEXT ("(%P|%t) ")
240 ACE_TEXT ("only one thread may be run ")
241 ACE_TEXT ("in a process on this platform\n")));
242 #endif /* ACE_HAS_THREADS */
244 peer_acceptor
.close ();
249 run_main (int, ACE_TCHAR
*[])
251 ACE_START_TEST (ACE_TEXT ("SOCK_Test"));
253 #ifndef ACE_LACKS_ACCEPT