Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / ACE / examples / IPC_SAP / SSL_SAP / SSL-server-fancy.cpp
blobe0a0c87b0f9fc4962123e7d28e760f52d9be7f58
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.
18 class Handler;
20 class Handler_Factory
22 // = TITLE
23 // Creates the oneway or twoway handlers.
24 public:
25 Handler_Factory ();
26 // Constructor.
28 ~Handler_Factory ();
29 // Destructor.
31 int handle_events ();
32 // Run the main event loop.
34 private:
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>
60 // = TITLE
61 // Base class for the oneway and twoway handlers.
63 friend class Handler_Factory;
64 // The factory has special permission. (to access svc ()).
66 public:
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
75 protected:
76 Handler (ACE_SSL_SOCK_Stream *ssl_stream);
77 // Constructor.
79 int parse_header_and_allocate_buffer (char *&buf,
80 ACE_INT32 *len);
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.
89 virtual int svc ();
90 // Template method entry point into the handler task.
92 virtual void print_results ();
93 // Print the results.
95 size_t total_bytes_;
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
110 // = TITLE
111 // Performs the twoway protocol.
112 public:
113 Twoway_Handler (ACE_SSL_SOCK_Stream *ssl_stream);
114 // Constructor.
116 private:
117 virtual int run ();
118 // Template Method hook called by <svc>.
121 class Oneway_Handler : public Handler
123 // = TITLE
124 public:
125 Oneway_Handler (ACE_SSL_SOCK_Stream *ssl_stream);
126 // Constructor.
128 private:
129 virtual int run ();
130 // Template Method hook called by <svc>.
132 virtual void print_results ();
133 // Print the results.
136 u_short
137 Options::port () const
139 return this->port_;
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_);
154 Options::~Options ()
158 Options::Options ()
159 : verbose_ (0),
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
174 switch (c)
176 case 'p':
177 this->port_ = ACE_OS::atoi (getopt.opt_arg ());
178 break;
179 case 'r':
180 this->reply_message_len_ = ACE_OS::atoi (getopt.opt_arg ());
181 break;
182 case 'v':
183 this->verbose_ = 1;
184 break;
185 default:
186 ACE_ERROR_RETURN ((LM_ERROR,
187 ACE_TEXT ("(%P|%t) usage: %n [-p <port>] [-v]")),
188 -1);
191 return 0;
194 // Options Singleton.
195 typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;
197 Handler::Handler (ACE_SSL_SOCK_Stream *ssl_stream)
198 : total_bytes_ (0),
199 message_count_ (0),
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,
213 ACE_TEXT ("%p\n"),
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 ()));
222 return 0;
226 Handler::close (u_long)
228 ACE_DEBUG ((LM_DEBUG,
229 ACE_TEXT ("(%P|%t) closing down %@\n"),
230 this));
232 delete this->ssl_stream_;
233 delete this;
235 return 0;
239 Handler::svc ()
241 // Timer logic.
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 ();
251 return result;
255 Handler::parse_header_and_allocate_buffer (char *&request,
256 ACE_INT32 *len)
258 ssize_t result = this->ssl_stream_ -> recv_n ((void *) len,
259 sizeof (ACE_INT32));
260 if (result == 0)
262 ACE_DEBUG ((LM_DEBUG,
263 ACE_TEXT ("(%P|%t) connected closed\n")));
264 return -1;
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")),
270 -1);
271 else
273 *len = ntohl (*len);
274 ACE_NEW_RETURN (request,
275 char[*len],
276 -1);
279 return 0;
282 void
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).
299 char *request = 0;
301 for (;;)
303 ACE_INT32 len = 0;
305 if (parse_header_and_allocate_buffer (request,
306 &len) == -1)
307 return -1;
309 // Subtract off the sizeof the length prefix.
310 ssize_t r_bytes =
311 this->ssl_stream_ -> recv_n (request,
312 len - sizeof (ACE_UINT32));
314 if (r_bytes == -1)
316 ACE_ERROR ((LM_ERROR,
317 ACE_TEXT ("%p\n"),
318 ACE_TEXT ("recv")));
319 break;
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")));
326 break;
328 else if (OPTIONS::instance ()->verbose ()
329 && ACE::write_n (ACE_STDOUT,
330 request,
331 r_bytes) != r_bytes)
332 ACE_ERROR ((LM_ERROR,
333 ACE_TEXT ("%p\n"),
334 ACE_TEXT ("ACE::write_n")));
335 else
337 ssize_t s_bytes =
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)
342 s_bytes = r_bytes;
344 if (this->ssl_stream_ -> send_n (request,
345 s_bytes) != s_bytes)
346 ACE_ERROR ((LM_ERROR,
347 ACE_TEXT ("%p\n"),
348 ACE_TEXT ("send_n")));
350 this->total_bytes_ += size_t (r_bytes);
351 this->message_count_++;
353 delete [] request;
354 request = 0;
357 delete [] request;
358 return 0;
361 Oneway_Handler::Oneway_Handler (ACE_SSL_SOCK_Stream *ssl_stream)
362 : Handler (ssl_stream)
366 void
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"),
374 et.real_time,
375 et.user_time,
376 et.system_time));
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_,
381 this->total_bytes_,
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).
393 char *request = 0;
395 for (;;)
397 ACE_INT32 len = 0;
399 if (parse_header_and_allocate_buffer (request,
400 &len) == -1)
401 return -1;
403 // Subtract off the sizeof the length prefix.
404 ssize_t r_bytes =
405 this->ssl_stream_ -> recv_n (request,
406 len - sizeof (ACE_UINT32));
408 if (r_bytes == -1)
410 ACE_ERROR ((LM_ERROR,
411 ACE_TEXT ("%p\n"),
412 ACE_TEXT ("recv")));
413 break;
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")));
420 break;
422 else if (OPTIONS::instance ()->verbose ()
423 && ACE::write_n (ACE_STDOUT,
424 request,
425 r_bytes) != r_bytes)
426 ACE_ERROR ((LM_ERROR,
427 ACE_TEXT ("%p\n"),
428 ACE_TEXT ("ACE::write_n")));
430 this->total_bytes_ += size_t (r_bytes);
431 this->message_count_++;
432 delete [] request;
433 request = 0;
436 delete [] request;
437 return 0;
440 // Create a twoway handler.
442 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.
450 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,
468 ACE_TEXT ("%p\n"),
469 ACE_TEXT ("open")),
470 -1);
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,
474 ACE_TEXT ("%p\n"),
475 ACE_TEXT ("get_local_addr")),
476 -1);
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 ()));
481 return 0;
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,
496 ACE_TEXT ("%p\n"),
497 ACE_TEXT ("accept")),
498 -1);
500 Handler *handler;
502 ACE_ALLOCATOR_RETURN (handler,
503 (*handler_factory) (new_stream),
504 -1);
506 ACE_DEBUG ((LM_DEBUG,
507 ACE_TEXT ("(%P|%t) spawning %s handler\n"),
508 handler_type));
510 if (handler->open () == -1)
511 return -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 ();
517 #else
518 handler->svc ();
519 handler->close (0);
520 return 0;
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)
540 return -1;
542 fd_set handles;
544 FD_ZERO (&handles);
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.
550 for (;;)
552 ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
553 fd_set temp = handles;
555 int result =
556 ACE_OS::select (int (this->oneway_acceptor_.get_handle ()) + 1,
557 (fd_set *) &temp,
560 timeout);
561 if (result == -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")));
568 else
570 if (FD_ISSET (this->twoway_acceptor_.get_handle (),
571 &temp))
572 this->create_handler (this->twoway_acceptor_,
573 &Handler_Factory::make_twoway_handler,
574 "twoway");
575 if (FD_ISSET (this->oneway_acceptor_.get_handle (),
576 &temp))
577 this->create_handler (this->oneway_acceptor_,
578 &Handler_Factory::make_oneway_handler,
579 "oneway");
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 ();