EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Help with UDP data handler

Started by Jeff Powell July 30, 2012
I posted this as part of a different question and nobody answered so I
will try again as it's own topic.

I have opened a udp socket with a datahandler.
I opened a second udp socket for sending multicast data when values change.
I get a connection, read from client, write back to client.
I get another connection. It does not go to the datahandler.
The main loop runs and multicast data continues to send properly.

What am I missing?

-- code --
if (!udp_open(&tsock, LOCAL_PORT, 0, 0, dataHandler))
{
printf("udp_lst_open failed!\n");
exit(0);
}
else
{
printf("Listener %s:%d\n",MY_IP_ADDRESS,LOCAL_PORT);
}
if (!udp_open(&usock, MBUS_PORT, resolve(MBUS_ADDRESS), MBUS_PORT,
NULL))
{
printf("udp_open failed!\n");
exit(0);
}

...

while (1)
{
idleProcessing(); // where values are processed and
multicast data is sent as needed.
tcp_tick(NULL);
}

...

int dataHandler(int event, udp_Socket *s, ll_Gather *g,
_udp_datagram_info *udi)
{
int status;
char cip[20];
CARDMSG_S *pkt;
if(handleUdp) // stops recursion, does not effect
handler death
return 1;
handleUdp=1;
if(event == UDP_DH_ICMPMSG) // from the example
{
return 1;
}
memset(&replyMsg, 0, sizeof (REPLYMSG_S));
xmem2root(pktbuf, g->data2, g->len2);
if(g->len3>0)
xmem2root(pktbuf+g->len2, g->data3, g->len3);
pkt=(CARDMSG_S*) &pktbuf;
inet_ntoa( cip, udi->remip);
printf("%s:%u Slot %d Type %d Device %d Offset %x Width %x Data %lx
%lx\n", cip, udi->remport, pkt->cSlot, pkt->cOperation, pkt->cDevice,
pkt->cOffset, pkt->cDataWidth, pkt->sData.longs[1], pkt->sData.longs[0] );
status = process_packet(pktbuf);
replyMsg.eStatus = status;
printf("Status: %x\n", status);
udp_sendto(s, (char*) &replyMsg, sizeof(REPLYMSG_S), udi->remip,
udi->remport); // straight from the
// even tried this but it does not help either. Returns 1 for NULL or
bytes recv'd for the incoming socket.
printf("Sent response %u\n", tcp_tick(NULL));
handleUdp=0;
return 1;
}

I can't tell you what you might doing wrong, but I can offer
some suggestions based on how I did something similar.
I did not use the callback feature. It seems to me there are
too many messages flying around to use this feature reliably.
 
I open several UDP sockets listening for broadcast messages.
 
 for(i=0;i    udp_extopen(&udpcon[i].socket,
                 IF_DEFAULT,
                 UDP_BROADCAST_PORT,
                 -1,-1,NULL,0,0);
 }

 
In the main loop I call a function that checks each socket for
a received message. If a message with data is found, the data
is copied to a buffer and passed to a paring routine.
 
// Look for incoming packets. for( s=0;s UdpParse( &udpcon[s]);
}
 
Occasionally, my program sends its own broadcast status.
When it does, it opens a UDP port, sends the message, then
closes the port.
 
// Open a Broadcast socket if( !udp_extopen( &udpsock.socket, IF_DEFAULT, UDP_BROADCAST_PORT-1, -1, UDP_BROADCAST_PORT, NULL, 0, 0) ) return;// Oops! // Build a status message FormatUDPStatusMsg( udpsock.buf); // Send it... udp_send( &udpsock.socket, udpsock.buf, strlen(udpsock.buf) ); udp_close( &udpsock.socket);
 
This works well in our system.
 
 
 
>From: Jeff Powell
>To: r...
>Sent: Monday, July 30, 2012 8:57 AM
>Subject: [rabbit-semi] Help with UDP data handler

>I posted this as part of a different question and nobody answered so I
>will try again as it's own topic.
>
>I have opened a udp socket with a datahandler.
>I opened a second udp socket for sending multicast data when values change.
>I get a connection, read from client, write back to client.
>I get another connection. It does not go to the datahandler.
>The main loop runs and multicast data continues to send properly.
>
>What am I missing?
>
>-- code --
>if (!udp_open(&tsock, LOCAL_PORT, 0, 0, dataHandler))
>{
>printf("udp_lst_open failed!\n");
>exit(0);
>}
>else
>{
>printf("Listener %s:%d\n",MY_IP_ADDRESS,LOCAL_PORT);
>}
>if (!udp_open(&usock, MBUS_PORT, resolve(MBUS_ADDRESS), MBUS_PORT,
>NULL))
>{
>printf("udp_open failed!\n");
>exit(0);
>}
>
>...
>
>while (1)
>{
>idleProcessing(); // where values are processed and
>multicast data is sent as needed.
>tcp_tick(NULL);
>}
>
>...
>
>int dataHandler(int event, udp_Socket *s, ll_Gather *g,
>_udp_datagram_info *udi)
>{
>int status;
>char cip[20];
>CARDMSG_S *pkt;
>if(handleUdp) // stops recursion, does not effect
>handler death
>return 1;
>handleUdp=1;
>if(event == UDP_DH_ICMPMSG) // from the example
>{
>return 1;
>}
>memset(&replyMsg, 0, sizeof (REPLYMSG_S));
>xmem2root(pktbuf, g->data2, g->len2);
>if(g->len3>0)
>xmem2root(pktbuf+g->len2, g->data3, g->len3);
>pkt=(CARDMSG_S*) &pktbuf;
>inet_ntoa( cip, udi->remip);
>printf("%s:%u Slot %d Type %d Device %d Offset %x Width %x Data %lx
>%lx\n", cip, udi->remport, pkt->cSlot, pkt->cOperation, pkt->cDevice,
>pkt->cOffset, pkt->cDataWidth, pkt->sData.longs[1], pkt->sData.longs[0] );
>status = process_packet(pktbuf);
>replyMsg.eStatus = status;
>printf("Status: %x\n", status);
>udp_sendto(s, (char*) &replyMsg, sizeof(REPLYMSG_S), udi->remip,
>udi->remport); // straight from the
>// even tried this but it does not help either. Returns 1 for NULL or
>bytes recv'd for the incoming socket.
>printf("Sent response %u\n", tcp_tick(NULL));
>handleUdp=0;
>return 1;
>}
>
Thanks that's a good idea. I may deploy this approach in my application.
Could you tell me how you are getting the remote IP and PORT for the
recvfrom call?

Thanks.

On 07/31/2012 12:29 PM, Steve Trigero wrote:
> I can't tell you what you might doing wrong, but I can offer
> some suggestions based on how I did something similar.
> I did not use the callback feature. It seems to me there are
> too many messages flying around to use this feature reliably.
> I open several UDP sockets listening for broadcast messages.
> for(i=0;i > udp_extopen(&udpcon[i].socket,
> IF_DEFAULT,
> UDP_BROADCAST_PORT,
> -1,-1,NULL,0,0);
> }
> In the main loop I call a function that checks each socket for
> a received message. If a message with data is found, the data
> is copied to a buffer and passed to a paring routine.
> // Look for incoming packets.
> for (s=0; s >
> if (!udp_peek(&udpcon[s].socket,NULL ) ){
> continue; // No packets...
> }
>
> numBytes = udp_recvfrom(&udpcon[s].socket,
> udpcon[s].buf,
> sizeof(udpcon[s].buf),
> &udpcon[s].ip,
> &udpcon[s].port );
> if (numBytes < 1 ){
> continue; // No data...
> }
> udpcon[s].buf[numBytes] = NUL;
> UdpParse(&udpcon[s] );
> }
> Occasionally, my program sends its own broadcast status.
> When it does, it opens a UDP port, sends the message, then
> closes the port.
> // Open a Broadcast socket
> if (!udp_extopen(&udpsock.socket,IF_DEFAULT,UDP_BROADCAST_PORT-1,
> -1,UDP_BROADCAST_PORT,NULL,0,0 ) )
> return; // Oops!
>
> // Build a status message
> FormatUDPStatusMsg(udpsock.buf );
>
> // Send it...
> udp_send(&udpsock.socket,udpsock.buf,strlen(udpsock.buf) );
> udp_close(&udpsock.socket );
> This works well in our system.
>
> *From:* Jeff Powell
> *To:* r...
> *Sent:* Monday, July 30, 2012 8:57 AM
> *Subject:* [rabbit-semi] Help with UDP data handler
>
> I posted this as part of a different question and nobody answered
> so I
> will try again as it's own topic.
>
> I have opened a udp socket with a datahandler.
> I opened a second udp socket for sending multicast data when
> values change.
> I get a connection, read from client, write back to client.
> I get another connection. It does not go to the datahandler.
> The main loop runs and multicast data continues to send properly.
>
> What am I missing?
>
> -- code --
> if (!udp_open(&tsock, LOCAL_PORT, 0, 0, dataHandler))
> {
> printf("udp_lst_open failed!\n");
> exit(0);
> }
> else
> {
> printf("Listener %s:%d\n",MY_IP_ADDRESS,LOCAL_PORT);
> }
> if (!udp_open(&usock, MBUS_PORT, resolve(MBUS_ADDRESS), MBUS_PORT,
> NULL))
> {
> printf("udp_open failed!\n");
> exit(0);
> }
>
> ...
>
> while (1)
> {
> idleProcessing(); // where values are processed and
> multicast data is sent as needed.
> tcp_tick(NULL);
> }
>
> ...
>
> int dataHandler(int event, udp_Socket *s, ll_Gather *g,
> _udp_datagram_info *udi)
> {
> int status;
> char cip[20];
> CARDMSG_S *pkt;
> if(handleUdp) // stops recursion, does not effect
> handler death
> return 1;
> handleUdp=1;
> if(event == UDP_DH_ICMPMSG) // from the example
> {
> return 1;
> }
> memset(&replyMsg, 0, sizeof (REPLYMSG_S));
> xmem2root(pktbuf, g->data2, g->len2);
> if(g->len3>0)
> xmem2root(pktbuf+g->len2, g->data3, g->len3);
> pkt=(CARDMSG_S*) &pktbuf;
> inet_ntoa( cip, udi->remip);
> printf("%s:%u Slot %d Type %d Device %d Offset %x Width %x Data %lx
> %lx\n", cip, udi->remport, pkt->cSlot, pkt->cOperation, pkt->cDevice,
> pkt->cOffset, pkt->cDataWidth, pkt->sData.longs[1],
> pkt->sData.longs[0] );
> status = process_packet(pktbuf);
> replyMsg.eStatus = status;
> printf("Status: %x\n", status);
> udp_sendto(s, (char*) &replyMsg, sizeof(REPLYMSG_S), udi->remip,
> udi->remport); // straight from the
> // even tried this but it does not help either. Returns 1 for NULL or
> bytes recv'd for the incoming socket.
> printf("Sent response %u\n", tcp_tick(NULL));
> handleUdp=0;
> return 1;
> }
The function udp_recvfrom() stuffs the ip and port values from the received datagram
into the ip and port function arguments. That way, if the message requires a response
I can respond to the specific ip and port of the host device.
 
steve

From: Jeff Powell
>To: r...
>Sent: Tuesday, July 31, 2012 2:01 PM
>Subject: Re: [rabbit-semi] Help with UDP data handler

>Thanks that's a good idea. I may deploy this approach in my application. Could you tell me how you are getting the remote IP and PORT for the recvfrom call?
>
>Thanks.
>On 07/31/2012 12:29 PM, Steve Trigero wrote:
>

>>I can't tell you what you might doing wrong, but I can offer
>>some suggestions based on how I did something similar.
>>I did not use the callback feature. It seems to me there are
>>too many messages flying around to use this feature reliably.
>> 
>>I open several UDP sockets listening for broadcast messages.
>> 
>> for(i=0;i >>   udp_extopen(&udpcon[i].socket,
>>                 IF_DEFAULT,
>>                 UDP_BROADCAST_PORT,
>>                 -1,-1,NULL,0,0);
>> }
>>In the main loop I call a function that checks each socket for
>>a received message. If a message with data is found, the data
>>is copied to a buffer and passed to a paring routine.
>>
>>// Look for incoming packets. for( s=0;s >>UdpParse( &udpcon[s]);
>>}
>>
>>Occasionally, my program sends its own broadcast status.
>>When it does, it opens a UDP port, sends the message, then
>>closes the port.
>>
>>// Open a Broadcast socket if( !udp_extopen( &udpsock.socket, IF_DEFAULT, UDP_BROADCAST_PORT-1, -1, UDP_BROADCAST_PORT, NULL, 0, 0) ) return;// Oops! // Build a status message FormatUDPStatusMsg( udpsock.buf); // Send it... udp_send( &udpsock.socket, udpsock.buf, strlen(udpsock.buf) ); udp_close( &udpsock.socket);
>>
>>This works well in our system.
>>
>>>
>>>From: Jeff Powell mailto:j...@yahoo.com
>>>To: r...
>>>Sent: Monday, July 30, 2012 8:57 AM
>>>Subject: [rabbit-semi] Help with UDP data handler
>>>
>>>
>>> 
>>>I posted this as part of a different question and nobody answered so I
>>>will try again as it's own topic.
>>>
>>>I have opened a udp socket with a datahandler.
>>>I opened a second udp socket for sending multicast data when values change.
>>>I get a connection, read from client, write back to client.
>>>I get another connection. It does not go to the datahandler.
>>>The main loop runs and multicast data continues to send properly.
>>>
>>>What am I missing?
>>>
>>>-- code --
>>>if (!udp_open(&tsock, LOCAL_PORT, 0, 0, dataHandler))
>>>{
>>>printf("udp_lst_open failed!\n");
>>>exit(0);
>>>}
>>>else
>>>{
>>>printf("Listener %s:%d\n",MY_IP_ADDRESS,LOCAL_PORT);
>>>}
>>>if (!udp_open(&usock, MBUS_PORT, resolve(MBUS_ADDRESS), MBUS_PORT,
>>>NULL))
>>>{
>>>printf("udp_open failed!\n");
>>>exit(0);
>>>}
>>>
>>>...
>>>
>>>while (1)
>>>{
>>>idleProcessing(); // where values are processed and
>>>multicast data is sent as needed.
>>>tcp_tick(NULL);
>>>}
>>>
>>>...
>>>
>>>int dataHandler(int event, udp_Socket *s, ll_Gather *g,
>>>_udp_datagram_info *udi)
>>>{
>>>int status;
>>>char cip[20];
>>>CARDMSG_S *pkt;
>>>if(handleUdp) // stops recursion, does not effect
>>>handler death
>>>return 1;
>>>handleUdp=1;
>>>if(event == UDP_DH_ICMPMSG) // from the example
>>>{
>>>return 1;
>>>}
>>>memset(&replyMsg, 0, sizeof (REPLYMSG_S));
>>>xmem2root(pktbuf, g->data2, g->len2);
>>>if(g->len3>0)
>>>xmem2root(pktbuf+g->len2, g->data3, g->len3);
>>>pkt=(CARDMSG_S*) &pktbuf;
>>>inet_ntoa( cip, udi->remip);
>>>printf("%s:%u Slot %d Type %d Device %d Offset %x Width %x Data %lx
>>>%lx\n", cip, udi->remport, pkt->cSlot, pkt->cOperation, pkt->cDevice,
>>>pkt->cOffset, pkt->cDataWidth, pkt->sData.longs[1], pkt->sData.longs[0] );
>>>status = process_packet(pktbuf);
>>>replyMsg.eStatus = status;
>>>printf("Status: %x\n", status);
>>>udp_sendto(s, (char*) &replyMsg, sizeof(REPLYMSG_S), udi->remip,
>>>udi->remport); // straight from the
>>>// even tried this but it does not help either. Returns 1 for NULL or
>>>bytes recv'd for the incoming socket.
>>>printf("Sent response %u\n", tcp_tick(NULL));
>>>handleUdp=0;
>>>return 1;
>>>}
>>>
>>>
>>>
>>>
The callback functionality works fine for me, so I put this answer for the history:

I use Dynamic C 10.70 and RCM6700.

My udp_open:
int local_port;
local_port = 2000; // for example
udp_open(&sock, local_port, -1, 0, comm_udp_rx_packet);

My callback function:
/*** BeginHeader comm_udp_rx_packet */
int comm_udp_rx_packet(int event, void *s, ll_Gather *g, _udp_datagram_info *info);
/*** EndHeader */
int comm_udp_rx_packet(int event, void *s, ll_Gather *g, _udp_datagram_info *info)
{
comm_udp_header_t *rx_header; // this is custom struct
char answer[5];
char cs;
int i;

if (
(event == UDP_DH_INDATA) &&
(info->len >= sizeof(comm_udp_header_t)) &&
(memcmp(g->data2, COMM_UDP_PREAMBLE, strlen(COMM_UDP_PREAMBLE)) == 0)
)
{
rx_header = (comm_udp_header_t*)g->data2;
rx_header->packet_id = ntohs(rx_header->packet_id);
rx_header->data_length = ntohs(rx_header->data_length);

// Checksum
cs = 0;
for (i=0; ilen2-1; i++) cs += g->data2[i];
if (cs != g->data2[g->len2-1]) {
answer[0] = ERROR_BAD_CHECKSUM;
answer[1] = cs;
answer[2] = g->data2[g->len2-1];
comm_udp_tx_packet(COMM_UDP_PACKET_ERROR, answer, 3, rx_header);
}
else

// Protocol Version
if (rx_header->protocol_version != COMM_UDP_PROTOCOL_VERSION) {
answer[0] = ERROR_BAD_PROTOCOL_VERSION;
answer[1] = COMM_UDP_PROTOCOL_VERSION;
answer[2] = rx_header->protocol_version;
comm_udp_tx_packet(COMM_UDP_PACKET_ERROR, answer, 3, rx_header);
}
else {
remote_ip = info->remip;
remote_port = info->remport;

// Good packet, so call the packet handling function.
comm_udp_rx_packet(rx_header, g->data2); // g->data2 points to the data part in the udp datagram
}
}

// The whole UDP RX traffic is handled in this function,
// so I don't add any data to the socket buffer for future use
return 1;
}

---=== Some info from the documentation ===---

Callback function parameters:

Event:
UDP_DH_INDATA - Normal received data
UDP_DH_ICMPMSG - ICMP message received for this socket

ll_Gather: (documented in NET.LIB)
typedef struct {
byte iface; // Destination interface
byte spare;
word len1; // Length of root data section
void * data1; // UDP header
word len2; // Length of first xmem section
long data2; // UDP data - xmem physical address
word len3; // Length of second xmem section
long data3; // not used
} ll_Gather;

_udp_datagram_info: (documented in udp_peek)
typedef struct {
longword remip; // Remote host IP address
word remport; // Remote host port number
int len; // Length of datagram
byte flags; // Bit mask (defined below)
byte iface; // Interface number
} _udp_datagram_info;
The flags field may have one of the following values:
UDI_ICMP_ERROR - This is an ICMP error entry.
UDI_TOS_MASK - Type-of-service bit mask.
UDI_BROADCAST_LL - Received on broadcast link layer address.
UDI_BROADCAST_IP - Received on broadcast network (IP) address.

This callback function should return:
0 - to continue with normal processing (i.e., add the datagram to the socket buffer)
1 - to indicate that the datagram has been processed and should not be added to the socket buffer

Memfault Beyond the Launch