1 // This example tests the features of the <ACE_SSL_SOCK_Acceptor>,
2 // <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform
3 // supports threads it uses a thread-per-connection concurrency model.
4 // Otherwise, it uses a single-threaded iterative server model.
6 #include "ace/Svc_Handler.h"
7 #include "ace/Singleton.h"
8 #include "ace/Profile_Timer.h"
9 #include "ace/Get_Opt.h"
10 #include "ace/Truncate.h"
11 #include "ace/OS_NS_sys_select.h"
13 #include "ace/SSL/SSL_SOCK_Acceptor.h"
15 #include "SSL-server-fancy.h"
17 // Forward declaration.
23 // Creates the oneway or twoway handlers.
32 // Run the main event loop.
35 int init_acceptors ();
36 // Initialize the acceptors.
38 int create_handler (ACE_SSL_SOCK_Acceptor
&acceptor
,
39 Handler
*(*handler_factory
) (ACE_SSL_SOCK_Stream
*),
40 const char *handler_type
);
41 // Factory that creates the right kind of <Handler>.
43 // = Factory functions.
45 static Handler
*make_twoway_handler (ACE_SSL_SOCK_Stream
*);
46 // Create a twoway handler.
48 static Handler
*make_oneway_handler (ACE_SSL_SOCK_Stream
*);
49 // Create a oneway handler.
51 ACE_SSL_SOCK_Acceptor twoway_acceptor_
;
52 // Twoway acceptor factory.
54 ACE_SSL_SOCK_Acceptor oneway_acceptor_
;
55 // Oneway acceptor factory.
58 class Handler
: public ACE_Svc_Handler
<ACE_SSL_SOCK_Stream
, ACE_NULL_SYNCH
>
61 // Base class for the oneway and twoway handlers.
63 friend class Handler_Factory
;
64 // The factory has special permission. (to access svc ()).
67 //FUZZ: disable check_for_lack_ACE_OS
68 virtual int open (void * = 0);
69 // Generic initialization method.
71 virtual int close (u_long
);
72 // Close down and delete this.
73 //FUZZ: enable check_for_lack_ACE_OS
76 Handler (ACE_SSL_SOCK_Stream
*ssl_stream
);
79 int parse_header_and_allocate_buffer (char *&buf
,
81 // Implement the generic code that's called from any of the subclass
82 // <run> methods to get the header and the buffer to read the data.
83 // This method factors out common code.
85 virtual int run () = 0;
86 // Hook method called by the <svc> template method to do the actual
87 // protocol. Must be overridden by the subclass.
90 // Template method entry point into the handler task.
92 virtual void print_results ();
96 // Total number of bytes received.
98 size_t message_count_
;
99 // Number of messages received.
101 ACE_Profile_Timer timer_
;
102 // Keeps track of how much time we're using.
104 ACE_SSL_SOCK_Stream
*ssl_stream_
;
105 //keep state information for a ssl_stream.
108 class Twoway_Handler
: public Handler
111 // Performs the twoway protocol.
113 Twoway_Handler (ACE_SSL_SOCK_Stream
*ssl_stream
);
118 // Template Method hook called by <svc>.
121 class Oneway_Handler
: public Handler
125 Oneway_Handler (ACE_SSL_SOCK_Stream
*ssl_stream
);
130 // Template Method hook called by <svc>.
132 virtual void print_results ();
133 // Print the results.
137 Options::port () const
143 Options::verbose () const
145 return this->verbose_
;
149 Options::reply_message_len () const
151 return ACE_Utils::truncate_cast
<int> (this->reply_message_len_
);
160 port_ (ACE_DEFAULT_SERVER_PORT
),
161 reply_message_len_ (24) // Default to the approximate size of an
162 // GIOP reply message.
167 Options::parse_args (int argc
, ACE_TCHAR
*argv
[])
169 //FUZZ: disable check_for_lack_ACE_OS
170 ACE_Get_Opt
getopt (argc
, argv
, ACE_TEXT ("p:r:v"), 1);
172 for (int c
; (c
= getopt ()) != -1; )
173 //FUZZ: enable check_for_lack_ACE_OS
177 this->port_
= ACE_OS::atoi (getopt
.opt_arg ());
180 this->reply_message_len_
= ACE_OS::atoi (getopt
.opt_arg ());
186 ACE_ERROR_RETURN ((LM_ERROR
,
187 ACE_TEXT ("(%P|%t) usage: %n [-p <port>] [-v]")),
194 // Options Singleton.
195 typedef ACE_Singleton
<Options
, ACE_SYNCH_RECURSIVE_MUTEX
> OPTIONS
;
197 Handler::Handler (ACE_SSL_SOCK_Stream
*ssl_stream
)
200 ssl_stream_ (ssl_stream
)
206 Handler::open (void *)
208 ACE_INET_Addr cli_addr
;
210 // Make sure we're not in non-blocking mode.
211 if (this->ssl_stream_
-> disable (ACE_NONBLOCK
) == -1)
212 ACE_ERROR_RETURN ((LM_ERROR
,
214 ACE_TEXT ("disable")),
217 ACE_DEBUG ((LM_DEBUG
,
218 ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
219 cli_addr
.get_host_name (),
220 cli_addr
.get_port_number ()));
226 Handler::close (u_long
)
228 ACE_DEBUG ((LM_DEBUG
,
229 ACE_TEXT ("(%P|%t) closing down %@\n"),
232 delete this->ssl_stream_
;
242 this->timer_
.start ();
244 // Invoke the hook method to run the specific test.
245 int result
= this->run ();
247 this->timer_
.stop ();
249 this->print_results ();
255 Handler::parse_header_and_allocate_buffer (char *&request
,
258 ssize_t result
= this->ssl_stream_
-> recv_n ((void *) len
,
262 ACE_DEBUG ((LM_DEBUG
,
263 ACE_TEXT ("(%P|%t) connected closed\n")));
266 else if (result
== -1 || result
!= sizeof (ACE_INT32
))
267 ACE_ERROR_RETURN ((LM_ERROR
,
268 ACE_TEXT ("(%P|%t) %p\n"),
269 ACE_TEXT ("recv_n failed")),
274 ACE_NEW_RETURN (request
,
283 Handler::print_results ()
287 Twoway_Handler::Twoway_Handler (ACE_SSL_SOCK_Stream
* ssl_stream
)
288 : Handler (ssl_stream
)
292 // Function entry point into the twoway server task.
295 Twoway_Handler::run ()
297 // Read data from client (terminate on error).
305 if (parse_header_and_allocate_buffer (request
,
309 // Subtract off the sizeof the length prefix.
311 this->ssl_stream_
-> recv_n (request
,
312 len
- sizeof (ACE_UINT32
));
316 ACE_ERROR ((LM_ERROR
,
321 else if (r_bytes
== 0)
323 ACE_DEBUG ((LM_DEBUG
,
324 ACE_TEXT ("(%P|%t) reached end of input, connection ")
325 ACE_TEXT ("closed by client\n")));
328 else if (OPTIONS::instance ()->verbose ()
329 && ACE::write_n (ACE_STDOUT
,
332 ACE_ERROR ((LM_ERROR
,
334 ACE_TEXT ("ACE::write_n")));
338 (ssize_t
) OPTIONS::instance ()->reply_message_len ();
340 // Don't try to send more than is in the request buffer!
341 if (s_bytes
> r_bytes
)
344 if (this->ssl_stream_
-> send_n (request
,
346 ACE_ERROR ((LM_ERROR
,
348 ACE_TEXT ("send_n")));
350 this->total_bytes_
+= size_t (r_bytes
);
351 this->message_count_
++;
361 Oneway_Handler::Oneway_Handler (ACE_SSL_SOCK_Stream
*ssl_stream
)
362 : Handler (ssl_stream
)
367 Oneway_Handler::print_results ()
369 ACE_Profile_Timer::ACE_Elapsed_Time et
;
370 this->timer_
.elapsed_time (et
);
372 ACE_DEBUG ((LM_DEBUG
,
373 ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
378 ACE_DEBUG ((LM_DEBUG
,
379 ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n"),
380 this->message_count_
,
382 (((double) this->total_bytes_
* 8) / et
.real_time
) / (double) (1024 * 1024),
383 ((et
.user_time
+ et
.system_time
) / (double) this->message_count_
) * ACE_ONE_SECOND_IN_USECS
));
386 // Function entry point into the oneway server task.
389 Oneway_Handler::run ()
391 // Read data from client (terminate on error).
399 if (parse_header_and_allocate_buffer (request
,
403 // Subtract off the sizeof the length prefix.
405 this->ssl_stream_
-> recv_n (request
,
406 len
- sizeof (ACE_UINT32
));
410 ACE_ERROR ((LM_ERROR
,
415 else if (r_bytes
== 0)
417 ACE_DEBUG ((LM_DEBUG
,
418 ACE_TEXT ("(%P|%t) reached end of input, connection ")
419 ACE_TEXT ("closed by client\n")));
422 else if (OPTIONS::instance ()->verbose ()
423 && ACE::write_n (ACE_STDOUT
,
426 ACE_ERROR ((LM_ERROR
,
428 ACE_TEXT ("ACE::write_n")));
430 this->total_bytes_
+= size_t (r_bytes
);
431 this->message_count_
++;
440 // Create a twoway handler.
443 Handler_Factory::make_twoway_handler (ACE_SSL_SOCK_Stream
*ssl_stream
)
445 return new Twoway_Handler (ssl_stream
);
448 // Create a oneway handler.
451 Handler_Factory::make_oneway_handler (ACE_SSL_SOCK_Stream
*ssl_stream
)
454 return new Oneway_Handler (ssl_stream
);
458 Handler_Factory::init_acceptors ()
460 // Create the oneway and twoway server addresses.
461 ACE_INET_Addr
twoway_server_addr (OPTIONS::instance ()->port ());
462 ACE_INET_Addr
oneway_server_addr (OPTIONS::instance ()->port () + 1);
464 // Create acceptors, reuse the address.
465 if (this->twoway_acceptor_
.open (twoway_server_addr
, 1) == -1
466 || this->oneway_acceptor_
.open (oneway_server_addr
, 1) == -1)
467 ACE_ERROR_RETURN ((LM_ERROR
,
471 else if (this->twoway_acceptor_
.get_local_addr (twoway_server_addr
) == -1
472 || this->oneway_acceptor_
.get_local_addr (oneway_server_addr
) == -1)
473 ACE_ERROR_RETURN ((LM_ERROR
,
475 ACE_TEXT ("get_local_addr")),
477 ACE_DEBUG ((LM_DEBUG
,
478 ACE_TEXT ("(%P|%t) starting twoway server at port %d and oneway server at port %d\n"),
479 twoway_server_addr
.get_port_number (),
480 oneway_server_addr
.get_port_number ()));
485 Handler_Factory::create_handler (
486 ACE_SSL_SOCK_Acceptor
&acceptor
,
487 Handler
* (*handler_factory
) (ACE_SSL_SOCK_Stream
* ),
488 const char *handler_type
)
490 ACE_SSL_SOCK_Stream
* new_stream
;
492 ACE_NEW_RETURN (new_stream
, ACE_SSL_SOCK_Stream
, -1);
494 if (acceptor
.accept (*new_stream
) == -1)
495 ACE_ERROR_RETURN ((LM_ERROR
,
497 ACE_TEXT ("accept")),
502 ACE_ALLOCATOR_RETURN (handler
,
503 (*handler_factory
) (new_stream
),
506 ACE_DEBUG ((LM_DEBUG
,
507 ACE_TEXT ("(%P|%t) spawning %s handler\n"),
510 if (handler
->open () == -1)
513 #if defined (ACE_MT_SAFE)
514 // Spawn a new thread and run the new connection in that thread of
515 // control using the <server> function as the entry point.
516 return handler
->activate ();
521 #endif /* ACE_HAS_THREADS */
524 Handler_Factory::Handler_Factory ()
528 Handler_Factory::~Handler_Factory ()
530 this->twoway_acceptor_
.close ();
531 this->oneway_acceptor_
.close ();
534 // Run the main event loop.
537 Handler_Factory::handle_events ()
539 if (this->init_acceptors () == -1)
545 FD_SET ((ACE_SOCKET
) this->twoway_acceptor_
.get_handle (), &handles
);
546 FD_SET ((ACE_SOCKET
) this->oneway_acceptor_
.get_handle (), &handles
);
548 // Performs the iterative server activities.
552 ACE_Time_Value
timeout (ACE_DEFAULT_TIMEOUT
);
553 fd_set temp
= handles
;
556 ACE_OS::select (int (this->oneway_acceptor_
.get_handle ()) + 1,
562 ACE_ERROR ((LM_ERROR
,
563 ACE_TEXT ("(%P|%t) %p\n"),
564 ACE_TEXT ("select")));
565 else if (result
== 0 && OPTIONS::instance ()->verbose ())
566 ACE_DEBUG ((LM_DEBUG
,
567 ACE_TEXT ("(%P|%t) select timed out\n")));
570 if (FD_ISSET (this->twoway_acceptor_
.get_handle (),
572 this->create_handler (this->twoway_acceptor_
,
573 &Handler_Factory::make_twoway_handler
,
575 if (FD_ISSET (this->oneway_acceptor_
.get_handle (),
577 this->create_handler (this->oneway_acceptor_
,
578 &Handler_Factory::make_oneway_handler
,
583 ACE_NOTREACHED (return 0;)
587 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
589 ACE_SSL_Context
*context
= ACE_SSL_Context::instance ();
591 context
->certificate ("./dummy.pem", SSL_FILETYPE_PEM
);
592 context
->private_key ("./key.pem", SSL_FILETYPE_PEM
);
594 OPTIONS::instance ()->parse_args (argc
, argv
);
596 Handler_Factory server
;
598 return server
.handle_events ();