1 #include "ace/SString.h"
2 #include "ace/Containers.h"
3 #include "ace/Get_Opt.h"
4 #include "TS_Server_Handler.h"
5 #include "ace/OS_NS_time.h"
6 #include "ace/Signal.h"
9 ACE_TS_Server_Acceptor::parse_args (int argc
, ACE_TCHAR
*argv
[])
11 ACE_TRACE ("ACE_TS_Server_Acceptor::parse_args");
13 int service_port
= ACE_DEFAULT_SERVER_PORT
;
15 ACE_LOG_MSG
->open (ACE_TEXT ("Time Service"));
17 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT ("p:"), 0);
19 for (int c
; (c
= get_opt ()) != -1; )
24 service_port
= ACE_OS::atoi (get_opt
.opt_arg ());
27 ACE_ERROR_RETURN ((LM_ERROR
,
28 ACE_TEXT ("%n:\n[-p server-port]\n"), 1),
32 this->service_addr_
.set (service_port
);
37 ACE_TS_Server_Acceptor::init (int argc
, ACE_TCHAR
*argv
[])
39 ACE_TRACE ("ACE_TS_Server_Acceptor::init");
41 // Use the options hook to parse the command line arguments and set
43 this->parse_args (argc
, argv
);
45 // Set the acceptor endpoint into listen mode (use the Singleton
46 // global Reactor...).
47 if (this->open (this->service_addr_
, ACE_Reactor::instance (),
49 &this->scheduling_strategy_
,
50 ACE_TEXT ("Time Server"),
51 ACE_TEXT ("ACE time service")) == -1)
52 ACE_ERROR_RETURN ((LM_ERROR
,
53 ACE_TEXT ("%n: %p on port %d\n"),
54 ACE_TEXT ("acceptor::open failed"),
55 this->service_addr_
.get_port_number ()),
58 // Ignore SIGPIPE so that each <SVC_HANDLER> can handle this on its
60 ACE_Sig_Action
sig ((ACE_SignalHandler
) SIG_IGN
, SIGPIPE
);
63 ACE_INET_Addr server_addr
;
65 // Figure out what port we're really bound to.
66 if (this->acceptor ().get_local_addr (server_addr
) == -1)
67 ACE_ERROR_RETURN ((LM_ERROR
,
69 ACE_TEXT ("get_local_addr")),
73 ACE_TEXT ("starting up Time Server at port %d on handle %d\n"),
74 server_addr
.get_port_number (),
75 this->acceptor ().get_handle ()));
79 // The following is a "Factory" used by the ACE_Service_Config and
80 // svc.conf file to dynamically initialize the state of the Time Server
82 ACE_SVC_FACTORY_DEFINE (ACE_TS_Server_Acceptor
)
84 // Default constructor.
85 ACE_TS_Server_Handler::ACE_TS_Server_Handler (ACE_Thread_Manager
*tm
)
86 : ACE_Svc_Handler
<ACE_SOCK_STREAM
, ACE_NULL_SYNCH
> (tm
)
88 ACE_TRACE ("ACE_TS_Server_Handler::ACE_TS_Server_Handler");
91 // Activate this instance of the ACE_TS_Server_Handler (called by the
92 // ACE_TS_Server_Acceptor).
95 ACE_TS_Server_Handler::open (void *)
97 ACE_TRACE ("ACE_TS_Server_Handler::open");
99 ACE_INET_Addr client_addr
;
101 // Determine the address of the client and display it.
102 if (this->peer ().get_remote_addr (client_addr
) == -1)
103 ACE_ERROR_RETURN ((LM_ERROR
,
105 ACE_TEXT ("get_remote_addr")),
108 ACE_DEBUG ((LM_DEBUG
,
109 ACE_TEXT ("(%t) accepted connection from host %C on fd %d\n"),
110 client_addr
.get_host_name (),
111 this->peer ().get_handle ()));
113 // Call down to our parent to register ourselves with the Reactor.
114 if (ACE_Svc_Handler
<ACE_SOCK_STREAM
, ACE_NULL_SYNCH
>::open (0) == -1)
115 ACE_ERROR_RETURN ((LM_ERROR
,
123 ACE_TS_Server_Handler::send_request (ACE_Time_Request
&request
)
125 ACE_TRACE ("ACE_TS_Server_Handler::send_request");
127 ssize_t length
= request
.encode (buffer
);
130 ACE_ERROR_RETURN ((LM_ERROR
,
132 ACE_TEXT ("encode failed")),
135 // Transmit request via a blocking send.
137 if (this->peer ().send_n (buffer
, length
) != length
)
138 ACE_ERROR_RETURN ((LM_ERROR
,
140 ACE_TEXT ("send_n failed")),
145 // Give up waiting (e.g., when a timeout occurs or a client shuts down
149 ACE_TS_Server_Handler::abandon ()
151 ACE_TRACE ("ACE_TS_Server_Handler::abandon");
153 // Note we are using the time field to report the errno in case of
155 ACE_Time_Request
rq (-1, errno
);
156 return this->send_request (rq
);
159 // Enable clients to limit the amount of time they'll wait
161 ACE_TS_Server_Handler::handle_timeout (const ACE_Time_Value
&, const void *)
163 ACE_TRACE ("ACE_TS_Server_Handler::handle_timeout");
164 return this->abandon ();
167 // Return the underlying ACE_HANDLE.
169 /* VIRTUAL */ ACE_HANDLE
170 ACE_TS_Server_Handler::get_handle () const
172 ACE_TRACE ("ACE_TS_Server_Handler::get_handle");
173 return this->peer ().get_handle ();
176 // Dispatch the appropriate operation to handle the client request.
179 ACE_TS_Server_Handler::dispatch ()
181 ACE_TRACE ("ACE_TS_Server_Handler::dispatch");
182 // Get the system time and then create an ACE_Time_Request
183 time_t t
= ACE_OS::time (0);
184 ACE_Time_Request
rq (ACE_Time_Request::TIME_UPDATE
, t
);
185 return this->send_request (rq
);
188 // Receive, frame, and decode the client's request. Note, this method
189 // should use non-blocking I/O.
192 ACE_TS_Server_Handler::recv_request ()
194 ACE_TRACE ("ACE_TS_Server_Handler::recv_request");
195 ssize_t
const bytes_expected
= this->time_request_
.size ();
197 // Since Time_Request messages are fixed size, read the entire
198 // message in one go.
199 ssize_t
const n
= this->peer ().recv ((void *) &this->time_request_
, bytes_expected
);
200 if (n
!= bytes_expected
)
205 ACE_DEBUG ((LM_DEBUG
,
206 ACE_TEXT ("****************** recv_request returned -1\n")));
209 ACE_ERROR ((LM_ERROR
,
210 ACE_TEXT ("%p got %d bytes, expected %d bytes\n"),
211 ACE_TEXT ("recv failed"),
216 // We've shutdown unexpectedly, let's abandon the
225 // Decode the request into host byte order.
226 if (this->time_request_
.decode () == -1)
228 ACE_ERROR ((LM_ERROR
,
230 ACE_TEXT ("decode failed")));
231 return this->abandon ();
237 // Callback method invoked by the ACE_Reactor when events arrive from
241 ACE_TS_Server_Handler::handle_input (ACE_HANDLE
)
243 ACE_TRACE ("ACE_TS_Server_Handler::handle_input");
245 if (this->recv_request () == -1)
248 return this->dispatch ();
251 ACE_TS_Server_Handler::~ACE_TS_Server_Handler ()
253 ACE_TRACE ("ACE_TS_Server_Handler::~ACE_TS_Server_Handler");
254 ACE_DEBUG ((LM_DEBUG
,
255 ACE_TEXT ("closing down Handle %d\n"),
256 this->get_handle ()));