📄 udp.c
字号:
* \ingroup udp_app_api
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 26.07.2002
* \param sochandle handle to UDP socket to use
* \param remip remote IP address to which data should be sent
* \param remport remote port number to which data should be sent
* \param buf pointer to data buffer (start of user data)
* \param blen buffer length in bytes (without space reserved at the
* beginning of buffer for headers)
* \param dlen length of user data to be sent (in bytes)
* \return
* \li -1 - Error (general error, e.g. parameters)
* \li -2 - ARP or lower layer not ready, try again later
* \li -3 - Socket closed or invalid local port
* \li >0 - OK (number represents number of bytes actually sent)
*
* \warning
* \li <i>buf</i> parameter is a pointer to data to be sent in
* user buffer. But note that there <b>MUST</b> be sufficient
* free buffer space before that data for UDP header (of #UDP_HLEN
* size).
*
* Use this function to send data over an already opened UDP socket.
*/
#ifdef IPv6
INT16 udp_send (INT8 sochandle, IPv6Addr * remip, UINT16 remport, UINT8* buf, UINT16 blen, UINT16 dlen)
#else
INT16 udp_send (INT8 sochandle, UINT32 remip, UINT16 remport, UINT8* buf, UINT16 blen, UINT16 dlen)
#endif
{
struct ucb* soc;
UINT8* user_buf_start;
UINT16 cs;
UINT8 cs_cnt;
INT16 i;
if( NO_OF_UDPSOCKETS < 0 )
return(-1);
if( NO_OF_UDPSOCKETS == 0 )
return(-1);
if( sochandle > NO_OF_UDPSOCKETS ) {
UDP_DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if( sochandle < 0 ) {
UDP_DEBUGOUT("Socket handle non-valid\r\n");
return(-1);
}
if(remip == 0) {
UDP_DEBUGOUT("Remote IP 0 not allowed\r\n");
return(-1);
}
if(remport == 0) {
UDP_DEBUGOUT("Remote port 0 not allowed\r\n");
return(-1);
}
if( dlen > blen )
dlen = blen;
if( (dlen + UDP_HLEN) > UDP_SEND_MTU)
dlen = UDP_SEND_MTU - UDP_HLEN;
soc = &udp_socket[sochandle]; /* Get referense */
if(soc->state != UDP_STATE_OPENED ) {
UDP_DEBUGOUT("UDP Socket Closed\r\n");
return(-3);
}
if(soc->locport == 0) {
UDP_DEBUGOUT("ERROR:Socket local port is zero\r\n");
return(-1);
}
user_buf_start = buf;
buf -= UDP_HLEN;
/* Put header */
*buf++ = (UINT8)(soc->locport >> 8);
*buf++ = (UINT8)soc->locport;
*buf++ = (UINT8)(remport >> 8);
*buf++ = (UINT8)remport;
*buf++ = (UINT8)((dlen + UDP_HLEN) >> 8);
*buf++ = (UINT8)(dlen + UDP_HLEN);
*buf++ = 0;
*buf = 0;
buf = user_buf_start;
buf -= UDP_HLEN;
/* Calculate checksum if needed */
cs = 0;
if( soc->opts & UDP_OPT_SEND_CS) {
cs = 0;
cs_cnt = 0;
/* Do it firstly to IP pseudo header */
#ifdef IPv6
#else
cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 24), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 16), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(localmachine.localip >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)localmachine.localip, cs_cnt++);
cs = ip_checksum(cs, (UINT8)(remip >> 24), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(remip >> 16), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(remip >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)remip, cs_cnt++);
cs = ip_checksum(cs, 0, cs_cnt++);
cs = ip_checksum(cs, (UINT8)IP_UDP, cs_cnt++);
cs = ip_checksum(cs, (UINT8)((dlen + UDP_HLEN) >> 8), cs_cnt++);
cs = ip_checksum(cs, (UINT8)(dlen + UDP_HLEN), cs_cnt++);
/* Go to UDP header + data */
buf = user_buf_start;
buf -= UDP_HLEN;
cs = ip_checksum_buf(cs, buf, dlen + UDP_HLEN);
cs = ~ cs;
#endif
if(cs == 0)
cs = 0xFFFF;
/* Save checksum in correct place */
buf = user_buf_start;
buf -= UDP_HLEN;
buf += 6;
*buf++ = (UINT8)(cs >> 8);
*buf = (UINT8)cs;
buf = user_buf_start;
buf -= UDP_HLEN;
}
/* Send it to IP */
UDP_DEBUGOUT("Sending UDP...\r\n");
i = process_ip_out(remip, IP_UDP, soc->tos, 100, buf, dlen + UDP_HLEN);
/* Errors? */
if( i < 0 )
return(i);
UDP_DEBUGOUT("UDP packet sent\r\n");
return(i - UDP_HLEN);
}
/** \brief Process received UDP frame
* \ingroup periodic_functions
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 15.07.2002
* \param frame pointer to received IP frame structure
* \param len length of data in bytes
* \return
* \li -1 - Error (packet not UDP, header errror or no socket for it)
* \li >0 - Packet OK
*
* Invoke this function to process received UDP frames. See main_demo.c for
* an example on how to accomplish this.
*/
INT16 process_udp_in(struct ip_frame* frame, UINT16 len)
{
struct ucb* soc;
UINT16 checksum;
UINT16 i;
INT8 sochandle;
/* Is this UDP? */
UDP_DEBUGOUT("Processing UDP...\n\r");
if( frame->protocol != IP_UDP ) {
UDP_DEBUGOUT("ERROR: The protocol is not UDP\n\r");
return(-1);
}
/* Start processing the message */
NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
received_udp_packet.sport = RECEIVE_NETWORK_W();
received_udp_packet.dport = RECEIVE_NETWORK_W();
received_udp_packet.tlen = RECEIVE_NETWORK_W();
received_udp_packet.checksum = RECEIVE_NETWORK_W();
/* Commented out by R42485
received_udp_packet.sport = ((UINT16)RECEIVE_NETWORK_B()) << 8;
received_udp_packet.sport |= RECEIVE_NETWORK_B();
received_udp_packet.dport = ((UINT16)RECEIVE_NETWORK_B()) << 8;
received_udp_packet.dport |= RECEIVE_NETWORK_B();
received_udp_packet.tlen = ((UINT16)RECEIVE_NETWORK_B()) << 8;
received_udp_packet.tlen |= RECEIVE_NETWORK_B();
received_udp_packet.checksum = ((UINT16)RECEIVE_NETWORK_B()) << 8;
received_udp_packet.checksum |= RECEIVE_NETWORK_B();
*/
if(received_udp_packet.tlen < UDP_HLEN ) {
UDP_DEBUGOUT("UDP frame too short\n\r");
return(-1);
}
/* Map UDP socket */
sochandle = -1;
for( i=0; i < NO_OF_UDPSOCKETS; i++) {
soc = &udp_socket[i]; /* Get referense */
if(soc->state != UDP_STATE_OPENED )
continue;
if(soc->locport != received_udp_packet.dport)
continue;
/* Socket found */
sochandle = (signed char)i;
break;
}
if( sochandle < 0 ) {
UDP_DEBUGOUT("No socket found for received UDP Packet\r\n");
/* TODO: Send ICMP */
return(-1);
}
/* Calculate checksum for received packet */
if(soc->opts & UDP_OPT_CHECK_CS) {
if(received_udp_packet.checksum != 0) {
checksum = 0;
i = 0;
/* Do it firstly to IP pseudo header */
#if defined(IPv6)
#else
checksum = ip_checksum(checksum, (UINT8)(frame->dip >> 24), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)(frame->dip >> 16), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)(frame->dip >> 8), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)frame->dip, (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 24), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 16), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)(frame->sip >> 8), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)frame->sip, (UINT8)i++);
checksum = ip_checksum(checksum, 0, (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)IP_UDP, (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)(len >> 8), (UINT8)i++);
checksum = ip_checksum(checksum, (UINT8)len, (UINT8)i++);
#endif
NETWORK_RECEIVE_INITIALIZE(frame->buf_index);
for(i=0; i < len; i++)
checksum = ip_checksum(checksum, RECEIVE_NETWORK_B(), (UINT8)i);
checksum = ~ checksum;
if(checksum != IP_GOOD_CS) {
UDP_DEBUGOUT("ERROR: UDP Checksum failed!\n\r");
return (-1);
}
}
UDP_DEBUGOUT("UDP Checksum OK\n\r");
}
received_udp_packet.buf_index = frame->buf_index + UDP_HLEN;
NETWORK_RECEIVE_INITIALIZE(received_udp_packet.buf_index);
/* Generate data event */
#if defined(IPv6)
#else
soc->event_listener(sochandle, UDP_EVENT_DATA, frame->sip, received_udp_packet.sport, received_udp_packet.buf_index, received_udp_packet.tlen - UDP_HLEN);
#endif
return(1);
}
/** \brief Returns next free (not used) local port number
* \author
* \li Jari Lahti (jari.lahti@violasystems.com)
* \date 19.10.2002
* \return
* \li 0 - no free ports!
* \li >0 - free local TCP port number
*
* Function attempts to find new local port number that can be used to
* establish a connection.
*/
UINT16 udp_getfreeport (void){
struct ucb* soc;
static UINT16 lastport = 1;
UINT16 start;
UINT16 i;
/* Try with every port to every socket untill free found */
for( start = lastport++; start != lastport; lastport++) {
if(lastport == UDP_PORTS_END)
lastport = 1;
for(i = 0; i < NO_OF_UDPSOCKETS; i++) {
soc = &udp_socket[i]; /* Get socket */
if( (soc->state > UDP_STATE_CLOSED) && (soc->locport == lastport) ) {
/* Blaah, this socket has reserved the port, go to next one */
break;
}
}
/* Did we found it? */
if( i == NO_OF_UDPSOCKETS)
break;
}
if(lastport == start) {
DEBUGOUT("Out of UDP ports!!\n\r");
return(0);
}
return(lastport);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -