1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
//=============================================================================
/**
* @file SOCK_Dgram_Bcast_Test.cpp
*
* $Id: SOCK_Dgram_Bcast_Test.cpp 93638 2011-03-24 13:16:05Z johnnyw $
*
* This simple broadcast test is intended to check if ACE is capable
* of sending and receiving broadcasts. In single host environment most
* errors related to invalid broadcast initialization will not manifest
* themself, because usually broadcast on localhost interface works
* correctly. For this reason one should run also this test on two distinct
* hosts in single LAN.
* Tests that a call to open with an any address binds to the any address
* for the protocol passed in.
*
*
* @author Marek Brudka (mbrudka@elka.pw.edu.pl)
*/
//=============================================================================
#include "test_config.h"
#include "ace/OS_NS_string.h"
#include "ace/OS_NS_unistd.h"
#include "ace/OS_NS_sys_time.h"
#include "ace/Log_Msg.h"
#include "ace/Get_Opt.h"
#include "ace/SOCK_Dgram_Bcast.h"
#include "ace/Thread_Manager.h"
#include "ace/Process.h"
#include "ace/Process_Manager.h"
static int dgram_port = 14521;
static int dgrams_no = 10;
static ACE_Time_Value dgram_recv_timeout( 5, 0 );
static ACE_exitcode receiver_exit_code = 0;
/*\brief Create and send single datagram
\param socket broadcast over this socket
\param datagram_no datagram identifier
\return -1 if error, 0 if OK
*/
int send_datagram (ACE_SOCK_Dgram_Bcast &socket, int datagram_no)
{
static char dgram_buffer[BUFSIZ];
ACE_OS::snprintf (dgram_buffer, sizeof(dgram_buffer),
"Datagram %d", datagram_no);
if (socket.send (dgram_buffer,
ACE_OS::strlen (dgram_buffer) + 1,
dgram_port) < 0 )
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("Cannot broadcast datagram")), -1);
else
ACE_DEBUG ((LM_INFO, ACE_TEXT ("%C sent\n"), dgram_buffer));
return 0;
}
/*\brief Send a sequence of datagrams with 1 second period
\note Th function employs dgram_port and dgrams_no global variables
\retval -1 if error
\retval 0 if sent
*/
int run_sender( )
{
ACE_DEBUG ((LM_INFO,
ACE_TEXT ("Sending %d datagrams on port %d\n"),
dgrams_no,
dgram_port));
ACE_SOCK_Dgram_Bcast socket;
if (socket.open (ACE_Addr::sap_any) != -1)
{
while (dgrams_no-- != 0)
{
if (send_datagram (socket, dgrams_no) < 0)
break;
ACE_OS::sleep (1);
}
socket.close ();
return (0);
}
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("Cannot open broadcast socket")), -1);
}
/*\brief Receive single datagram
\note The function employes dgram_port and dgram_recv_timeout variables
\retval -1 if not received,
\retval 0 received a datagrams
*/
int run_receiver ()
{
ACE_DEBUG
((LM_INFO,
ACE_TEXT ("Receiving datagrams from port %d with timeout %d ms\n"),
dgram_port, dgram_recv_timeout.msec ()));
ACE_SOCK_Dgram socket;
ACE_INET_Addr remote ;
static char dgram_buffer[BUFSIZ];
if (socket.open (ACE_INET_Addr (dgram_port)) != -1)
if (socket.recv (dgram_buffer, sizeof (dgram_buffer),
remote, 0, &dgram_recv_timeout) > 0)
{
ACE_DEBUG ((LM_INFO, ACE_TEXT ("%C received\n"), dgram_buffer));
return 0;
}
else
{
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("Cannot receive datagrams")), -1);
}
else
{
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%p: %d\n"),
ACE_TEXT ("Cannot open broadcast socket on port"), dgram_port), -1);
}
}
#if !defined (ACE_HAS_PROCESS_SPAWN) && defined (ACE_HAS_THREADS)
/* \brief Thread main function to run run_receiver function
\note run_receiver return valu is stored in receiver_exit_code global variable
*/
static ACE_THR_FUNC_RETURN run_thread_receiver (void *)
{
receiver_exit_code = run_receiver ();
return 0;
}
#endif /* !defined (ACE_HAS_PROCESS_SPAWN) && defined (ACE_HAS_THREADS) */
/* \brief Just runs automatic tests
Function sends a number of datagrams, spawns child thread or process and
tries to receive at least one datagram.
\retval 0 datagram was received
\retval -1 datagram was not received
*/
int run_auto_test (const ACE_TCHAR *prog_name)
{
#if defined (ACE_HAS_PROCESS_SPAWN)
ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running auto_tests in process mode\n")));
ACE_Process_Options opts;
pid_t child_pid;
opts.command_line (ACE_TEXT ("%s -p %d -t %d -a -r"),
prog_name, dgram_port, dgram_recv_timeout.msec ());
if ((child_pid = ACE_Process_Manager::instance ()->spawn (opts)) == -1)
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn_n()")), -1);
#elif defined (ACE_HAS_THREADS)
ACE_UNUSED_ARG (prog_name);
ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running auto_tests in thread mode\n")));
if (ACE_Thread_Manager::instance ()->spawn (run_thread_receiver) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%p\n"),
ACE_TEXT ("spawn_n ()")), -1);
#else
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("Cannot run in auto_test mode without fork or threads.\n")),
-1);
#endif /* defined (ACE_HAS_PROCESS_SPAWN) */
ACE_DEBUG ((LM_INFO,
ACE_TEXT ("Sending datagrams on port %d in auto_test mode\n"),
dgram_port));
ACE_SOCK_Dgram_Bcast socket;
if (socket.open (ACE_Addr::sap_any) != -1)
{
// send datagrams until child finishes
while (1)
{
send_datagram (socket, dgrams_no--);
ACE_Time_Value child_timeout (1);
#if defined (ACE_HAS_PROCESS_SPAWN)
if (ACE_Process_Manager::instance ()->wait (child_pid,
child_timeout,
&receiver_exit_code) == child_pid)
break;
#else /* ACE_HAS_THREADS */
// sleep 1 second or wait for child thread
child_timeout += ACE_OS::gettimeofday () ;
if (ACE_Thread_Manager::instance ()->wait (&child_timeout) == 0)
break;
#endif
}
socket.close ();
ACE_DEBUG ((LM_INFO, ACE_TEXT ("Child finished with %d exit code\n"),
receiver_exit_code));
}
else
ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
ACE_TEXT ("Cannot open broadcast socket")), -1);
return (receiver_exit_code);
}
void print_usage (void)
{
ACE_OS::printf("Usage:SOCK_Dgram_Bast_Test [-p port] [-n dgrams_no] [-t timeout_ms] [-s] [-r]\n"
"\tp broadcast port [14521]\n"
"\tn number of datagrams to broadcast [30] (<0 infinite)\n"
"\tt timeout in seconds for receive [5] (<=0 infinite)\n"
"\ts send datagrams and exit\n"
"\tr receive one datagram and exit\n\n"
"\t run auto-test when no r and s option is passed\n"
"\t test failures are minifested by -1 exit value, otherwise 0\n");
}
int run_main (int argc, ACE_TCHAR *argv[])
{
// parse options and run in appropriate mode
int opt = 0;
int auto_test_recv = 0;
int result = 0;
ACE_Get_Opt opts (argc, argv, ACE_TEXT ("p:t:n:sra"));
while ((opt = opts ()) != -1)
switch (opt)
{
case 'a':
auto_test_recv = 1;
break;
case 's':
return (run_sender());
case 'r':
{
if (auto_test_recv)
{
ACE_START_TEST (ACE_TEXT ("SOCK_Dgram_Bcast_Test_Child"));
result = run_receiver ();
ACE_END_TEST;
return result;
}
return (run_receiver ());
}
case 'n':
dgrams_no = ACE_OS::atoi (opts.opt_arg ());
break;
case 't':
dgram_recv_timeout.msec (ACE_OS::atoi (opts.opt_arg ()));
break;
case 'p':
dgram_port = ACE_OS::atoi (opts.opt_arg ());
break;
default:
print_usage ();
return -1;
}
ACE_START_TEST (ACE_TEXT ("SOCK_Dgram_Bcast_Test"));
result = run_auto_test (argc > 0 ? argv[0] : ACE_TEXT ("SOCK_Dgram_Bcast_Test"));
ACE_END_TEST;
return result;
}
|