Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / tests / SOCK_Test.cpp
blob63e74c76a63e384d10a01b6a078a162c81b6df74
2 //=============================================================================
3 /**
4 * @file SOCK_Test.cpp
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
10 * exchange data.
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";
30 void *
31 client (void *arg)
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);
56 else
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")));
64 // Test Bug 3606
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,
68 true, // read_ready
69 true, // write_ready
70 false);
71 // we expect the handle to be at least write_ready since it is freshly connected.
72 if (result == -1)
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")));
84 char buf[1];
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")));
94 return 0;
97 void *
98 server (void *arg)
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
106 // calls...
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);
112 char buf[BUFSIZ];
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);
119 if (result == -1)
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]);
143 t++;
146 if (r_bytes == 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")));
155 // Close endpoint.
156 if (new_stream.close () == -1)
157 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("close")));
158 return 0;
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")));
164 else
165 ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("recv_n")), 0);
170 if (result == -1)
172 if (errno == EWOULDBLOCK)
173 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) no connections available, shutting down\n")));
174 else
175 ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n"), ACE_TEXT ("accept")));
178 return 0;
181 void
182 spawn ()
184 // Acceptor
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")));
194 else
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")))
202 case -1:
203 ACE_ERROR ((LM_ERROR,
204 ACE_TEXT ("(%P|%t) %p\n"),
205 ACE_TEXT ("fork failed"),
206 1));
207 ACE_OS::abort ();
208 case 0:
209 client (&server_addr);
210 ACE_OS::exit (0);
211 /* NOTREACHED */
212 default:
213 server ((void *) &peer_acceptor);
214 ACE_OS::wait ();
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"),
224 1));
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"),
233 1));
235 // Wait for the threads to exit.
236 ACE_Thread_Manager::instance ()->wait ();
237 #else
238 ACE_ERROR ((LM_INFO,
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
254 spawn ();
255 #endif
257 ACE_END_TEST;
258 return 0;