Merge branch 'master' into jwi-bcc64xsingletonwarning
[ACE_TAO.git] / ACE / examples / Reactor / Dgram / Dgram.cpp
blob0c2920df69a1df8ed5339377e9789f2708f5d628
1 // Exercise the <ACE_SOCK_Dgram> wrapper along with the <ACE_Reactor>.
2 // This test simply ping-pongs datagrams back and forth between the
3 // peer1 and peer2 processes. This test can be run in two ways:
4 //
5 // 1. Stand-alone -- e.g.,
6 //
7 // % ./Dgram
8 //
9 // which will spawn a child process and run peer1 and peer2
10 // in different processes on the same machine.
12 // 2. Distributed -- e.g.,
14 // # Peer1
15 // % ./Dgram 10002 tango.cs.wustl.edu 10003 peer1
17 // # Peer1
18 // % ./Dgram 10003 tango.cs.wustl.edu 10002 peer2
20 // which will run peer1 and peer2 in different processes
21 // on the same or different machines. Note that you MUST
22 // give the name "peer1" as the final argument to one and
23 // only one of the programs so that the test will work properly.
25 #include "ace/OS_main.h"
26 #include "ace/OS_NS_string.h"
27 #include "ace/OS_NS_unistd.h"
28 #include "ace/Reactor.h"
29 #include "ace/Process.h"
30 #include "ace/SOCK_Dgram.h"
31 #include "ace/INET_Addr.h"
32 #include "ace/Log_Msg.h"
35 // Port used to receive for dgrams.
36 static u_short port1;
38 class Dgram_Endpoint : public ACE_Event_Handler
40 public:
41 Dgram_Endpoint (const ACE_INET_Addr &local_addr);
43 // = Hook methods inherited from the <ACE_Event_Handler>.
44 virtual ACE_HANDLE get_handle () const;
45 virtual int handle_input (ACE_HANDLE handle);
46 virtual int handle_timeout (const ACE_Time_Value & tv,
47 const void *arg = 0);
48 virtual int handle_close (ACE_HANDLE handle,
49 ACE_Reactor_Mask close_mask);
51 //FUZZ: disable check_for_lack_ACE_OS
52 int send (const char *buf, size_t len, const ACE_INET_Addr &);
53 // Send the <buf> to the peer.
54 //FUZZ: enable check_for_lack_ACE_OS
56 private:
57 ACE_SOCK_Dgram endpoint_;
58 // Wrapper for sending/receiving dgrams.
61 int
62 Dgram_Endpoint::send (const char *buf,
63 size_t len,
64 const ACE_INET_Addr &addr)
66 return this->endpoint_.send (buf, len, addr);
69 Dgram_Endpoint::Dgram_Endpoint (const ACE_INET_Addr &local_addr)
70 : endpoint_ (local_addr)
74 ACE_HANDLE
75 Dgram_Endpoint::get_handle () const
77 return this->endpoint_.get_handle ();
80 int
81 Dgram_Endpoint::handle_close (ACE_HANDLE handle,
82 ACE_Reactor_Mask)
84 ACE_UNUSED_ARG (handle);
86 this->endpoint_.close ();
87 delete this;
88 return 0;
91 int
92 Dgram_Endpoint::handle_input (ACE_HANDLE)
94 char buf[BUFSIZ];
95 ACE_INET_Addr from_addr;
97 ACE_DEBUG ((LM_DEBUG,
98 "(%P|%t) activity occurred on handle %d!\n",
99 this->endpoint_.get_handle ()));
101 ssize_t n = this->endpoint_.recv (buf,
102 sizeof buf,
103 from_addr);
105 if (n == -1)
106 ACE_ERROR ((LM_ERROR,
107 "%p\n",
108 "handle_input"));
109 else
110 ACE_DEBUG ((LM_DEBUG,
111 "(%P|%t) buf of size %d = %*s\n",
114 buf));
115 return 0;
119 Dgram_Endpoint::handle_timeout (const ACE_Time_Value &,
120 const void *)
122 ACE_DEBUG ((LM_DEBUG,
123 "(%P|%t) timed out for endpoint\n"));
124 return 0;
127 static int
128 run_test (u_short localport,
129 const ACE_TCHAR *remotehost,
130 u_short remoteport,
131 const ACE_TCHAR *peer)
133 ACE_INET_Addr remote_addr (remoteport,
134 remotehost);
135 ACE_INET_Addr local_addr (localport);
137 Dgram_Endpoint *endpoint;
139 ACE_NEW_RETURN (endpoint,
140 Dgram_Endpoint (local_addr),
141 -1);
143 // Read data from other side.
144 if (ACE_Reactor::instance ()->register_handler
145 (endpoint,
146 ACE_Event_Handler::READ_MASK) == -1)
147 ACE_ERROR_RETURN ((LM_ERROR,
148 "ACE_Reactor::register_handler"),
149 -1);
151 char buf[BUFSIZ];
152 ACE_OS::strcpy (buf, "Data to transmit");
153 size_t len = ACE_OS::strlen (buf);
155 if (ACE_OS::strncmp (peer, ACE_TEXT("peer1"), 5) == 0)
157 ACE_DEBUG ((LM_DEBUG,
158 "(%P|%t) sending data\n"));
160 for (size_t i = 0; i < 20; i++)
162 endpoint->send (buf, len, remote_addr);
163 ACE_DEBUG ((LM_DEBUG,
164 "(%P|%t) .\n"));
165 ACE_OS::sleep (1);
169 for (int i = 0; i < 40; i++)
171 // Wait up to 10 seconds for data.
172 ACE_Time_Value tv (10, 0);
174 if (ACE_Reactor::instance ()->handle_events (tv) <= 0)
175 ACE_ERROR_RETURN ((LM_DEBUG,
176 "(%P|%t) %p\n",
177 "handle_events"),
178 -1);
180 ACE_DEBUG ((LM_DEBUG,
181 "(%P|%t) return from handle events\n"));
183 endpoint->send (buf, len, remote_addr);
185 ACE_DEBUG ((LM_DEBUG,
186 "(%P|%t) .\n"));
189 if (ACE_Reactor::instance ()->remove_handler
190 (endpoint,
191 ACE_Event_Handler::READ_MASK) == -1)
192 ACE_ERROR_RETURN ((LM_ERROR,
193 "ACE_Reactor::remove_handler"),
194 -1);
195 ACE_DEBUG ((LM_DEBUG,
196 "(%P|%t) exiting\n"));
197 return 0;
201 ACE_TMAIN (int argc, ACE_TCHAR *argv[])
203 // Estabish call backs and socket names.
205 port1 = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
206 const ACE_TCHAR *remotehost = argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST;
207 const u_short port2 = argc > 3 ? ACE_OS::atoi (argv[3]) : port1 + 1;
209 // Providing the fourth command line argument indicate we don't want
210 // to spawn a new process. On Win32, we use this to exec the new
211 // program.
212 if (argc > 4)
213 run_test (port1, remotehost, port2, argv[4]);
214 else
216 ACE_DEBUG ((LM_DEBUG,
217 "(%P|%t) local port = %d, remote host = %s, remote port = %d\n",
218 port1,
219 remotehost,
220 port2));
222 ACE_Process_Options options;
223 options.command_line (ACE_TEXT ("%s %d %s %d %c"),
224 argv[0],
225 port1,
226 remotehost,
227 port2,
228 'c');
230 // This has no effect on NT and will spawn a process that exec
231 // the above run_test function.
232 options.creation_flags (ACE_Process_Options::NO_EXEC);
234 ACE_Process new_process;
235 switch (new_process.spawn (options))
237 case -1:
238 return -1;
240 case 0:
241 run_test (port1,
242 remotehost,
243 port2,
244 ACE_TEXT("peer1"));
245 break;
247 default:
248 run_test (port2,
249 remotehost,
250 port1,
251 ACE_TEXT("peer2"));
252 new_process.wait ();
253 break;
256 return 0;