Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / examples / IPC_SAP / SOCK_SAP / CPP-inserver-fancy.cpp
blob221c55d4f15a67ab0692f8af21dff9f7913b8141
1 // This example tests the features of the <ACE_SOCK_Acceptor>,
2 // <ACE_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/OS_main.h"
7 #include "ace/SOCK_Acceptor.h"
8 #include "ace/Svc_Handler.h"
9 #include "ace/Singleton.h"
10 #include "ace/Profile_Timer.h"
11 #include "ace/Get_Opt.h"
12 #include "ace/OS_NS_sys_select.h"
14 #include "CPP-inserver-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_SOCK_Acceptor &acceptor,
39 Handler *(*handler_factory) (ACE_HANDLE),
40 const char *handler_type);
41 // Factory that creates the right kind of <Handler>.
43 // = Factory functions.
44 static Handler *make_twoway_handler (ACE_HANDLE);
45 // Create a twoway handler.
47 static Handler *make_oneway_handler (ACE_HANDLE);
48 // Create a oneway handler.
50 ACE_SOCK_Acceptor twoway_acceptor_;
51 // Twoway acceptor factory.
53 ACE_SOCK_Acceptor oneway_acceptor_;
54 // Oneway acceptor factory.
57 class Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
59 // = TITLE
60 // Base class for the oneway and twoway handlers.
62 friend class Handler_Factory;
63 // The factory has special permission. (to access svc ()).
65 public:
66 //FUZZ: disable check_for_lack_ACE_OS
67 virtual int open (void * = 0);
68 // Generic initialization method.
70 virtual int close (u_long);
71 // Close down and delete this.
72 //FUZZ: enable check_for_lack_ACE_OS
74 protected:
75 Handler (ACE_HANDLE handle);
76 // Constructor.
78 int parse_header_and_allocate_buffer (char *&buf,
79 ACE_INT32 *len);
80 // Implement the generic code that's called from any of the subclass
81 // <run> methods to get the header and the buffer to read the data.
82 // This method factors out common code.
84 virtual int run () = 0;
85 // Hook method called by the <svc> template method to do the actual
86 // protocol. Must be overridden by the subclass.
88 virtual int svc ();
89 // Template method entry point into the handler task.
91 virtual void print_results ();
92 // Print the results.
94 size_t total_bytes_;
95 // Total number of bytes received.
97 size_t message_count_;
98 // Number of messages received.
100 ACE_Profile_Timer timer_;
101 // Keeps track of how much time we're using.
104 class Twoway_Handler : public Handler
106 // = TITLE
107 // Performs the twoway protocol.
108 public:
109 Twoway_Handler (ACE_HANDLE handle);
110 // Constructor.
112 private:
113 virtual int run ();
114 // Template Method hook called by <svc>.
117 class Oneway_Handler : public Handler
119 // = TITLE
120 public:
121 Oneway_Handler (ACE_HANDLE handle);
122 // Constructor.
124 private:
125 virtual int run ();
126 // Template Method hook called by <svc>.
128 virtual void print_results ();
129 // Print the results.
132 u_short
133 Options::port () const
135 return this->port_;
139 Options::verbose () const
141 return this->verbose_;
145 Options::reply_message_len () const
147 return this->reply_message_len_;
150 Options::~Options ()
154 Options::Options ()
155 : verbose_ (0),
156 port_ (ACE_DEFAULT_SERVER_PORT),
157 reply_message_len_ (24) // Default to the approximate size of an
158 // GIOP reply message.
163 Options::parse_args (int argc, ACE_TCHAR *argv[])
165 //FUZZ: disable check_for_lack_ACE_OS
166 ACE_Get_Opt getopt (argc, argv, ACE_TEXT("p:r:v"), 1);
168 for (int c; (c = getopt ()) != -1; )
169 //FUZZ: enable check_for_lack_ACE_OS
170 switch (c)
172 case 'p':
173 this->port_ = ACE_OS::atoi (getopt.opt_arg ());
174 break;
175 case 'r':
176 this->reply_message_len_ = ACE_OS::atoi (getopt.opt_arg ());
177 break;
178 case 'v':
179 this->verbose_ = 1;
180 break;
181 default:
182 ACE_ERROR_RETURN ((LM_ERROR,
183 "(%P|%t) usage: %n [-p <port>] [-v]"),
184 -1);
187 return 0;
190 // Options Singleton.
191 typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;
193 Handler::Handler (ACE_HANDLE handle)
194 : total_bytes_ (0),
195 message_count_ (0)
197 this->peer ().set_handle (handle);
201 Handler::open (void *)
203 ACE_INET_Addr cli_addr;
205 // Make sure we're not in non-blocking mode.
206 if (this->peer ().disable (ACE_NONBLOCK) == -1)
207 ACE_ERROR_RETURN ((LM_ERROR,
208 "%p\n",
209 "disable"),
212 ACE_DEBUG ((LM_DEBUG,
213 "(%P|%t) client %s connected from %d on handle %d\n",
214 cli_addr.get_host_name (),
215 cli_addr.get_port_number (),
216 this->peer ().get_handle ()));
217 return 0;
221 Handler::close (u_long)
223 ACE_DEBUG ((LM_DEBUG,
224 "(%P|%t) closing down %x\n",
225 this));
226 delete this;
227 return 0;
231 Handler::svc ()
233 // Timer logic.
234 this->timer_.start ();
236 // Invoke the hook method to run the specific test.
237 int result = this->run ();
239 this->timer_.stop ();
241 this->print_results ();
243 return result;
247 Handler::parse_header_and_allocate_buffer (char *&request,
248 ACE_INT32 *len)
250 ssize_t result = this->peer ().recv_n ((void *) len,
251 sizeof (ACE_INT32));
252 if (result == 0)
254 ACE_DEBUG ((LM_DEBUG,
255 "(%P|%t) connected closed\n"));
256 return -1;
258 else if (result == -1 || result != sizeof (ACE_INT32))
259 ACE_ERROR_RETURN ((LM_ERROR,
260 "(%P|%t) %p\n",
261 "recv_n failed"),
262 -1);
263 else
265 *len = ntohl (*len);
266 ACE_NEW_RETURN (request,
267 char[*len],
268 -1);
271 return 0;
274 void
275 Handler::print_results ()
279 Twoway_Handler::Twoway_Handler (ACE_HANDLE handle)
280 : Handler (handle)
284 // Function entry point into the twoway server task.
287 Twoway_Handler::run ()
289 // Read data from client (terminate on error).
291 char *request = 0;
293 for (;;)
295 ACE_INT32 len = 0;
297 if (parse_header_and_allocate_buffer (request,
298 &len) == -1)
299 return -1;
301 // Subtract off the sizeof the length prefix.
302 ssize_t r_bytes = this->peer ().recv_n (request,
303 len - sizeof (ACE_UINT32));
305 if (r_bytes == -1)
307 ACE_ERROR ((LM_ERROR,
308 "%p\n",
309 "recv"));
310 break;
312 else if (r_bytes == 0)
314 ACE_DEBUG ((LM_DEBUG,
315 "(%P|%t) reached end of input, connection closed by client\n"));
316 break;
318 else if (OPTIONS::instance ()->verbose ()
319 && ACE::write_n (ACE_STDOUT,
320 request,
321 r_bytes) != r_bytes)
322 ACE_ERROR ((LM_ERROR,
323 "%p\n",
324 "ACE::write_n"));
325 else
327 ssize_t s_bytes = (ssize_t) OPTIONS::instance ()->reply_message_len ();
329 // Don't try to send more than is in the request buffer!
330 if (s_bytes > r_bytes)
331 s_bytes = r_bytes;
333 if (this->peer ().send_n (request,
334 s_bytes) != s_bytes)
335 ACE_ERROR ((LM_ERROR,
336 "%p\n",
337 "send_n"));
339 this->total_bytes_ += size_t (r_bytes);
340 this->message_count_++;
342 delete [] request;
343 request = 0;
346 delete [] request;
347 return 0;
350 Oneway_Handler::Oneway_Handler (ACE_HANDLE handle)
351 : Handler (handle)
355 void
356 Oneway_Handler::print_results ()
358 ACE_Profile_Timer::ACE_Elapsed_Time et;
359 this->timer_.elapsed_time (et);
361 ACE_DEBUG ((LM_DEBUG,
362 ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
363 et.real_time,
364 et.user_time,
365 et.system_time));
367 ACE_DEBUG ((LM_DEBUG,
368 ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n"),
369 this->message_count_,
370 this->total_bytes_,
371 (((double) this->total_bytes_ * 8) / et.real_time) / (double) (1024 * 1024),
372 ((et.user_time + et.system_time) / (double) this->message_count_) * ACE_ONE_SECOND_IN_USECS));
375 // Function entry point into the oneway server task.
378 Oneway_Handler::run ()
380 // Read data from client (terminate on error).
382 char *request = 0;
384 for (;;)
386 ACE_INT32 len = 0;
388 if (parse_header_and_allocate_buffer (request,
389 &len) == -1)
390 return -1;
392 // Subtract off the sizeof the length prefix.
393 ssize_t r_bytes = this->peer ().recv_n (request,
394 len - sizeof (ACE_UINT32));
396 if (r_bytes == -1)
398 ACE_ERROR ((LM_ERROR,
399 "%p\n",
400 "recv"));
401 break;
403 else if (r_bytes == 0)
405 ACE_DEBUG ((LM_DEBUG,
406 "(%P|%t) reached end of input, connection closed by client\n"));
407 break;
409 else if (OPTIONS::instance ()->verbose ()
410 && ACE::write_n (ACE_STDOUT,
411 request,
412 r_bytes) != r_bytes)
413 ACE_ERROR ((LM_ERROR,
414 "%p\n",
415 "ACE::write_n"));
417 this->total_bytes_ += size_t (r_bytes);
418 this->message_count_++;
419 delete [] request;
420 request = 0;
423 delete [] request;
424 return 0;
427 // Create a twoway handler.
429 Handler *
430 Handler_Factory::make_twoway_handler (ACE_HANDLE handle)
432 return new Twoway_Handler (handle);
435 // Create a oneway handler.
437 Handler *
438 Handler_Factory::make_oneway_handler (ACE_HANDLE handle)
440 return new Oneway_Handler (handle);
444 Handler_Factory::init_acceptors ()
446 // Create the oneway and twoway server addresses.
447 ACE_INET_Addr twoway_server_addr (OPTIONS::instance ()->port ());
448 ACE_INET_Addr oneway_server_addr (OPTIONS::instance ()->port () + 1);
450 // Create acceptors, reuse the address.
451 if (this->twoway_acceptor_.open (twoway_server_addr, 1) == -1
452 || this->oneway_acceptor_.open (oneway_server_addr, 1) == -1)
453 ACE_ERROR_RETURN ((LM_ERROR,
454 "%p\n",
455 "open"),
456 -1);
457 else if (this->twoway_acceptor_.get_local_addr (twoway_server_addr) == -1
458 || this->oneway_acceptor_.get_local_addr (oneway_server_addr) == -1)
459 ACE_ERROR_RETURN ((LM_ERROR,
460 "%p\n",
461 "get_local_addr"),
462 -1);
463 ACE_DEBUG ((LM_DEBUG,
464 "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",
465 twoway_server_addr.get_port_number (),
466 oneway_server_addr.get_port_number ()));
467 return 0;
471 Handler_Factory::create_handler (ACE_SOCK_Acceptor &acceptor,
472 Handler * (*handler_factory) (ACE_HANDLE),
473 const char *handler_type)
475 ACE_SOCK_Stream new_stream;
477 if (acceptor.accept (new_stream) == -1)
478 ACE_ERROR_RETURN ((LM_ERROR,
479 "%p\n",
480 "accept"),
481 -1);
483 Handler *handler;
485 ACE_ALLOCATOR_RETURN (handler,
486 (*handler_factory) (new_stream.get_handle ()),
487 -1);
489 ACE_DEBUG ((LM_DEBUG,
490 "(%P|%t) spawning %s handler\n",
491 handler_type));
493 if (handler->open () == -1)
494 return -1;
496 #if defined (ACE_MT_SAFE)
497 // Spawn a new thread and run the new connection in that thread of
498 // control using the <server> function as the entry point.
499 return handler->activate ();
500 #else
501 handler->svc ();
502 handler->close (0);
503 return 0;
504 #endif /* ACE_HAS_THREADS */
507 Handler_Factory::Handler_Factory ()
511 Handler_Factory::~Handler_Factory ()
513 this->twoway_acceptor_.close ();
514 this->oneway_acceptor_.close ();
517 // Run the main event loop.
520 Handler_Factory::handle_events ()
522 if (this->init_acceptors () == -1)
523 return -1;
525 fd_set handles;
527 FD_ZERO (&handles);
528 FD_SET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (),
529 &handles);
530 FD_SET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (),
531 &handles);
533 // Performs the iterative server activities.
535 for (;;)
537 ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
538 fd_set temp = handles;
540 int result = ACE_OS::select (int (this->oneway_acceptor_.get_handle ()) + 1,
541 (fd_set *) &temp,
544 timeout);
545 if (result == -1)
546 ACE_ERROR ((LM_ERROR,
547 "(%P|%t) %p\n",
548 "select"));
549 else if (result == 0 && OPTIONS::instance ()->verbose ())
550 ACE_DEBUG ((LM_DEBUG,
551 "(%P|%t) select timed out\n"));
552 else
554 if (FD_ISSET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (),
555 &temp))
556 this->create_handler (this->twoway_acceptor_,
557 &Handler_Factory::make_twoway_handler,
558 "twoway");
559 if (FD_ISSET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (),
560 &temp))
561 this->create_handler (this->oneway_acceptor_,
562 &Handler_Factory::make_oneway_handler,
563 "oneway");
567 ACE_NOTREACHED (return 0;)
571 ACE_TMAIN (int argc, ACE_TCHAR *argv[])
573 OPTIONS::instance ()->parse_args (argc, argv);
575 Handler_Factory server;
577 return server.handle_events ();
579 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Singleton, Options, ACE_SYNCH_RECURSIVE_MUTEX);