Hello,
I am running UDP protocol on RCM3315 and the task is to listen on one UDP Multicast Port and IP and send to another UDP Multicast Port and IP. I am also allowing for Telnet connection on another socket.
The Rabbit board is on a switch which handles multicast traffic.
The board is assigned a static IP address on the switch.
The following code is running tcp_tick and my_tick() which handles the states of connection. The switch cases handle send and receive port states.
Why do I need to use udp_send() with a heartbeat message to be able to receive packets?
See under “// Check the timer–if it has expired, send another heartbeat packet” comment.
If I comment the heartbeat message out, the receive interrupts but reads all zeroes.
Any idea of what the heartbeat message doing?
void main()
{
unsigned int connectionDelayCnt = 0, statusDelayCnt = 0;
io_init();
memset(state, 0, sizeof(state));
while (1) {
costate //TCPIP
{
tcp_listen (&socket, TCPIPPORT, 0, 0, NULL, 0);
while (!sock_established(&socket) && sock_bytesready(&socket) == -1)
{
remoteConnection = 0;
yield;
}
while (sock_established(&socket))
{
if (!remoteConnection)
{
tcpipCommandCounter = 0;
delay (100);
remoteConnection = 1;
tcpipCommandReceived = 1; //must fool TransmitData routine
sprintf (outputBuf, "%s", commandPrompt);
TransmitTCPData(prompt);
tcpipCommandReceived = 0;
}
ReadTCPIPData();
yield;
}
sock_close (&socket);
}
costate
{
if (pd_havelink(0) != 0) // check if link exists
// Drive the TCP/IP stack
tcp_tick(NULL);
// Drive UDP state machine
my_tick();
}
costate //Send Message approximately every second
{
if (++statusDelayCnt == 5000)
{
statusDelayCnt = 0;
sendmsg();
}
}
costate //CONNECTION
{
if (++connectionDelayCnt == 500)
{
connectionDelayCnt = 0;
SetConnection();
}
}
} // end while (1)
} // end main()
// Do processing on the multicast sockets
xmem void my_tick(void)
{
auto int i;
auto int retval;
auto longword remip;
auto word remport;
auto char ipbuf[16];
unsigned long msg_id;
// Process socket 0 (Multicast Write)
switch (state[0].state) {
case MCAST_OPENING:
// Open the multicast socket
retval = udp_extopen(&state[0].sock, IF_ETH0,
myFlashArray.port_udp_multi_write, inet_addr
(myFlashArray.ip_udp_multi_write),
myFlashArray.port_udp_multi_write, NULL, 0, 0);
if (retval == 0) {
// Error opening the socket
printf("Error opening socket %d!
", 0);
state[0].state = MCAST_CLOSED;
}
else {
// Set the interval timer, and advance to the next state
state[0].timer = set_timeout(conf[0].interval);
state[0].state = MCAST_CLOSING;
}
break;
case MCAST_CLOSING:
sock_close(&state[0].sock);
state[0].state = MCAST_CLOSED;
break;
case MCAST_CLOSED:
// Do nothing
break;
default:
// There is no transition to a state other than the ones listed
// above. So, if we reach this "state", then something is
// dreadfully wrong.
printf("Error in state machine! Not in a known state...
");
exit(1);
}
// Process socket 1 (Multicast Read)
switch (state[1].state) {
case MCAST_OPENING:
// Open the multicast socket
retval = udp_extopen(&state[1].sock, IF_ETH0,
myFlashArray.port_udp_multi_read, inet_addr
(myFlashArray.ip_udp_multi_read),
myFlashArray.port_udp_multi_read, NULL, 0, 0);
if (retval == 0) {
// Error opening the socket
printf("Error opening socket %d!
", 1);
state[1].state = MCAST_CLOSED;
}
else {
// Set the interval timer, and advance to the next state
state[1].timer = set_timeout(conf[1].interval);
state[1].state = MCAST_RUNNING;
}
break;
case MCAST_RUNNING:
// Check for any incoming datagrams
retval = udp_recvfrom(&state[1].sock, bufferUDP, strlen(bufferUDP),
&remip, &remport);
if (retval < -1) {
// Error reading from the socket
printf("Error reading from socket %d!
", 1);
state[1].state = MCAST_CLOSING;
}
else if (retval >= 0) {
// NULL terminate the buffer and print a message
bufferUDP[retval] = '\0';
inet_ntoa(ipbuf, remip);
printf("Received on socket %d from %s port %u:
", 1, ipbuf, remport);
printf("%02X%02X%02X%02X%02X%s
", bufferUDP[0], bufferUDP[1], bufferUDP[2],
bufferUDP[3], bufferUDP[4], &bufferUDP[5]);
msg_id = ((0x000000FF & bufferUDP[0]) << 24) | ((0x000000FF & bufferUDP[1]) << 16) | ((0x000000FF & bufferUDP[2]) << 8) | (0x000000FF & bufferUDP[3]);
if (msg_id == myFlashArray.cmd_query_id)
{
outputBufUDP[0] = (0xFF000000 & myFlashArray.query_resp_id) >> 24;
outputBufUDP[1] = (0x00FF0000 & myFlashArray.query_resp_id) >> 16;
outputBufUDP[2] = (0x0000FF00 & myFlashArray.query_resp_id) >> 8;
outputBufUDP[3] = 0x000000FF & myFlashArray.query_resp_id;
outputBufUDP[4] = bufferUDP[4]; //cmd/query enumerator
if (bufferUDP[4] == 0x01)
{
sprintf(&outputBufUDP[5], "%s", myFlashArray.unitid);
udp_sendto(&state[0].sock, outputBufUDP, strlen(&outputBufUDP[5]) + 6, inet_addr(myFlashArray.ip_udp_multi_write), myFlashArray.port_udp_multi_write);
}
if (bufferUDP[4] == 0x02)
{
sprintf(&outputBufUDP[5], "%s", myFlashArray.serialnum);
udp_sendto(&state[0].sock, outputBufUDP, strlen(&outputBufUDP[5]) + 6, inet_addr(myFlashArray.ip_udp_multi_write), myFlashArray.port_udp_multi_write);
}
}
}
// Check the timer--if it has expired, send another heartbeat packet
if (chk_timeout(state[1].timer)) {
state[1].timer = set_timeout(conf[1].interval);
sprintf(bufferUDP, "Heartbeat packet #%ld on socket %d
",
state[1].pkts_sent, 1);
retval = udp_send(&state[1].sock, bufferUDP, strlen(bufferUDP)+1);
state[1].pkts_sent += 1;
if (retval < 0) {
printf("Error sending on socket %d!
", 1);
state[1].state = MCAST_CLOSING;
}
}
break;
case MCAST_CLOSING:
sock_close(&state[1].sock);
state[1].state = MCAST_CLOSED;
break;
case MCAST_CLOSED:
// Do nothing
break;
default:
// There is no transition to a state other than the ones listed
// above. So, if we reach this "state", then something is
// dreadfully wrong.
printf("Error in state machine! Not in a known state...
");
exit(1);
}
}