2 //=============================================================================
4 * @file Thread_Pool_Reactor_SSL_Test.cpp
6 * This program is a torture test of threaded SSL usage. It
7 * is based on the tests/Thread_Pool_Reactor_Test and adds
8 * SSL stuff submitted by Robert Handl <robert.handl@ehpt.com>.
9 * It starts by spawning several server threads waiting to handle
10 * events. Several other client threads are spawned right after
11 * to initiate connections to server threads. Each connection
12 * adds a new Svc_Handler into the TP_Reactor and sends out
13 * several "requests" to the server thread. After the connection
14 * is closed, the Svc_Handler is removed from the TP_Reactor.
15 * Each message is treated as a separate request by the server so
16 * two consecutive requests might be serviced by two different
19 * Usage: Thread_Pool_Reactor_Test_SSL [-r <hostname:port#>]
20 * [-s <server thr#>] [-c <client thr#>] [-d <delay>]
21 * [-i <client conn attempt#>] [-n <client request# per conn>]
24 * <hostname:port#>: ACE_DEFAULT_RENDEZVOUS
25 * <server thr#>: ACE_MAX_THREADS
26 * <client thr#>: ACE_MAX_ITERATIONS
27 * <client conn attempt#>: ACE_MAX_ITERATIONS
28 * <client req# per conn>: ACE_MAX_THREADS
31 * @author Irfan Pyarali <irfan@cs.wustl.edu> and Nanbor Wang <nanbor@cs.wustl.edu>
33 //=============================================================================
35 #include "../test_config.h"
36 #include "ace/OS_NS_string.h"
37 #include "ace/OS_NS_unistd.h"
38 #include "ace/Get_Opt.h"
39 #include "ace/Acceptor.h"
40 #include "ace/Thread_Manager.h"
41 #include "ace/TP_Reactor.h"
42 #include "ace/SSL/SSL_SOCK_Connector.h"
43 #include "ace/SSL/SSL_SOCK_Acceptor.h"
45 #if defined (ACE_HAS_THREADS)
47 #include "Thread_Pool_Reactor_SSL_Test.h"
48 typedef ACE_Strategy_Acceptor
<Request_Handler
, ACE_SSL_SOCK_Acceptor
>
51 // Accepting end point. This is actually "localhost:10010", but some
52 // platform couldn't resolve the name so we use the IP address
54 static const ACE_TCHAR
*rendezvous
= ACE_TEXT ("127.0.0.1:10010");
56 // Total number of server threads.
57 static size_t svr_thrno
= ACE_MAX_THREADS
;
59 // Total number of client threads.
60 static size_t cli_thrno
= ACE_MAX_THREADS
;
62 // Total connection attempts of a client thread.
63 static size_t cli_conn_no
= ACE_MAX_ITERATIONS
;
65 // Total requests a client thread sends.
66 static size_t cli_req_no
= ACE_MAX_THREADS
;
68 // Delay before a thread sending the next request (in msec.)
69 static int req_delay
= 50;
72 parse_arg (int argc
, ACE_TCHAR
*argv
[])
74 //FUZZ: disable check_for_lack_ACE_OS
75 ACE_Get_Opt
getopt (argc
, argv
, ACE_TEXT ("r:s:c:d:i:n:"));
79 while ((c
= getopt ()) != -1)
81 //FUZZ: enable check_for_lack_ACE_OS
84 case 'r': // hostname:port
85 rendezvous
= getopt
.opt_arg ();
88 svr_thrno
= ACE_OS::atoi (getopt
.opt_arg ());
91 cli_thrno
= ACE_OS::atoi (getopt
.opt_arg ());
94 req_delay
= ACE_OS::atoi (getopt
.opt_arg ());
97 cli_conn_no
= ACE_OS::atoi (getopt
.opt_arg ());
100 cli_req_no
= ACE_OS::atoi (getopt
.opt_arg ());
103 ACE_ERROR ((LM_ERROR
,
104 "Usage: Thread_Pool_Reactor_SSL_Test [-r <hostname:port#>]"
105 "\t[-s <server thr#>] [-c <client thr#>] [-d <delay>]"
106 "\t[-i <client conn attempt#>]"
107 "[-n <client request# per conn>]\n"));
113 Request_Handler::Request_Handler (ACE_Thread_Manager
*thr_mgr
)
114 : ACE_Svc_Handler
<ACE_SSL_SOCK_Stream
, ACE_MT_SYNCH
> (thr_mgr
),
117 // Make sure we use TP_Reactor with this class (that's the whole
119 this->reactor (ACE_Reactor::instance ());
123 Request_Handler::handle_input (ACE_HANDLE fd
)
125 ACE_TCHAR buffer
[BUFSIZ
];
127 ssize_t result
= this->peer ().recv (&len
, sizeof (ACE_TCHAR
));
130 && this->peer ().recv_n (buffer
, len
* sizeof (ACE_TCHAR
))
131 == static_cast<ssize_t
> (len
* sizeof (ACE_TCHAR
)))
133 ++this->nr_msgs_rcvd_
;
135 ACE_DEBUG ((LM_DEBUG
,
136 "(%t) svr input; fd: 0x%x; input: %s\n",
139 if (ACE_OS::strcmp (buffer
, ACE_TEXT ("shutdown")) == 0)
140 ACE_Reactor::end_event_loop ();
144 ACE_DEBUG ((LM_DEBUG
,
145 "(%t) Request_Handler: 0x%x peer closed (0x%x)\n",
151 Request_Handler::handle_close (ACE_HANDLE fd
, ACE_Reactor_Mask
)
153 ACE_DEBUG ((LM_DEBUG
,
154 "(%t) svr close; fd: 0x%x, rcvd %d msgs\n",
156 this->nr_msgs_rcvd_
));
157 if (this->nr_msgs_rcvd_
!= cli_req_no
)
159 "(%t) Handler 0x%x: Expected %d messages; got %d\n",
162 this->nr_msgs_rcvd_
));
168 reactor_event_hook (ACE_Reactor
*)
170 ACE_DEBUG ((LM_DEBUG
,
171 "(%t) handling events ....\n"));
176 static ACE_THR_FUNC_RETURN
179 // Server thread function.
181 ACE_Reactor::instance ()->run_reactor_event_loop (&reactor_event_hook
);
184 ACE_ERROR_RETURN ((LM_ERROR
,
186 "Error handling events"),
189 ACE_DEBUG ((LM_DEBUG
,
190 "(%t) I am done handling events. Bye, bye\n"));
195 static ACE_THR_FUNC_RETURN
196 cli_worker (void *arg
)
198 // Client thread function.
199 ACE_INET_Addr
addr (rendezvous
);
200 ACE_SSL_SOCK_Stream stream
;
201 ACE_SSL_SOCK_Connector connect
;
202 ACE_Time_Value
delay (0, req_delay
);
203 size_t len
= * reinterpret_cast<ACE_TCHAR
*> (arg
);
205 for (size_t i
= 0 ; i
< cli_conn_no
; i
++)
207 if (connect
.connect (stream
, addr
) < 0)
209 ACE_ERROR ((LM_ERROR
,
215 for (size_t j
= 0; j
< cli_req_no
; j
++)
217 ACE_DEBUG ((LM_DEBUG
,
218 "(%t) conn_worker handle 0x%x, req %d\n",
219 stream
.get_handle (),
221 if (stream
.send_n (arg
,
222 (len
+ 1) * sizeof (ACE_TCHAR
)) == -1)
224 ACE_ERROR ((LM_ERROR
,
229 ACE_OS::sleep (delay
);
238 static ACE_THR_FUNC_RETURN
242 const ACE_TCHAR
*msg
= ACE_TEXT ("Message from Connection worker");
243 ACE_TCHAR buf
[BUFSIZ
];
244 buf
[0] = ACE_OS::strlen (msg
) + 1;
245 ACE_OS::strcpy (&buf
[1], msg
);
247 ACE_INET_Addr
addr (rendezvous
);
250 "(%t) Spawning %d client threads...\n",
252 int grp
= ACE_Thread_Manager::instance ()->spawn_n (cli_thrno
,
255 ACE_ASSERT (grp
!= -1);
257 ACE_Thread_Manager::instance ()->wait_grp (grp
);
259 ACE_DEBUG ((LM_DEBUG
,
260 "(%t) Client threads done; shutting down...\n"));
261 ACE_SSL_SOCK_Stream stream
;
262 ACE_SSL_SOCK_Connector connect
;
264 if (connect
.connect (stream
, addr
) == -1)
265 ACE_ERROR ((LM_ERROR
,
266 "(%t) %p Error while connecting\n",
269 const ACE_TCHAR
*sbuf
= ACE_TEXT ("\011shutdown");
271 ACE_DEBUG ((LM_DEBUG
,
272 "shutdown stream handle = %x\n",
273 stream
.get_handle ()));
275 if (stream
.send_n (sbuf
, (ACE_OS::strlen (sbuf
) + 1) * sizeof (ACE_TCHAR
)) == -1)
276 ACE_ERROR ((LM_ERROR
,
286 run_main (int argc
, ACE_TCHAR
*argv
[])
288 ACE_START_TEST (ACE_TEXT ("Thread_Pool_Reactor_SSL_Test"));
290 ACE_SSL_Context
*context
= ACE_SSL_Context::instance ();
291 // Note - the next two strings are naked on purpose... the arguments to
292 // the ACE_SSL_Context methods are const char *, not ACE_TCHAR *.
293 context
->certificate ("dummy.pem", SSL_FILETYPE_PEM
);
294 context
->private_key ("key.pem", SSL_FILETYPE_PEM
);
296 parse_arg (argc
, argv
);
298 // Changed the default
300 ACE_Reactor
new_reactor (&sr
);
301 ACE_Reactor::instance (&new_reactor
);
304 ACE_INET_Addr
accept_addr (rendezvous
);
306 if (acceptor
.open (accept_addr
) == -1)
307 ACE_ERROR_RETURN ((LM_ERROR
,
313 ACE_TEXT ("(%t) Spawning %d server threads...\n"),
315 ACE_Thread_Manager::instance ()->spawn_n (svr_thrno
,
317 ACE_Thread_Manager::instance ()->spawn (worker
);
319 ACE_Thread_Manager::instance ()->wait ();
327 run_main (int, ACE_TCHAR
*[])
329 ACE_START_TEST (ACE_TEXT ("Thread_Pool_Reactor_SSL_Test"));
332 "threads not supported on this platform\n"));
337 #endif /* ACE_HAS_THREADS */