Files
FireBee_SVN/BaS_gcc/net/udp.c

184 lines
3.5 KiB
C

/*
* File: udp.c
* Purpose: User Datagram Protocol driver
*
* Notes:
*
* Modifications:
*
*/
#include "bas_types.h"
#include "bas_printf.h"
#include "net.h"
#include <stddef.h>
#define DBG_UDP
#if defined(DBG_UDP)
#define dbg(format, arg...) do { xprintf("DEBUG: " format "\r\n", ##arg); } while (0)
#else
#define dbg(format, arg...) do { ; } while (0)
#endif /* DBG_UDP */
typedef struct
{
uint16_t port;
void (*handler)(NIF *, NBUF *);
} UDP_BOUND_PORT;
#define UDP_MAX_PORTS (5) /* plenty for this implementation */
static UDP_BOUND_PORT udp_port_table[UDP_MAX_PORTS];
static uint16_t udp_port;
void udp_init(void)
{
int index;
for (index = 0; index < UDP_MAX_PORTS; ++index)
{
udp_port_table[index].port = 0;
}
udp_port = DEFAULT_UDP_PORT; /* next free port */
}
void udp_prime_port(uint16_t init_port)
{
udp_port = init_port;
}
void udp_bind_port(uint16_t port, void (*handler)(NIF *, NBUF *))
{
int index;
for (index = 0; index < UDP_MAX_PORTS; ++index)
{
if (udp_port_table[index].port == 0)
{
udp_port_table[index].port = port;
udp_port_table[index].handler = handler;
return;
}
}
}
void udp_free_port(uint16_t port)
{
int index;
for (index = 0; index < UDP_MAX_PORTS; ++index)
{
if (udp_port_table[index].port == port)
{
udp_port_table[index].port = 0;
return;
}
}
}
static void *udp_port_handler(uint16_t port)
{
int index;
for (index = 0; index < UDP_MAX_PORTS; ++index)
{
if (udp_port_table[index].port == port)
{
return (void *)udp_port_table[index].handler;
}
}
return NULL;
}
uint16_t udp_obtain_free_port(void)
{
uint16_t port;
port = udp_port;
if (--udp_port <= 255)
udp_port = DEFAULT_UDP_PORT;
return port;
}
int udp_send(NIF *nif, uint8_t *dest, int sport, int dport, NBUF *pNbuf)
{
uint8_t *myip;
if (nif == NULL)
{
dbg("%s: nif is NULL\r\n", __FUNCTION__);
return 0;
}
/*
* This function takes data and creates a UDP frame and
* passes it onto the IP layer
*/
udp_frame_hdr *udpframe;
udpframe = (udp_frame_hdr *) &pNbuf->data[UDP_HDR_OFFSET];
/* Set UDP source port */
udpframe->src_port = (uint16_t) sport;
/* Set UDP destination port */
udpframe->dest_port = (uint16_t) dport;
/* Set length */
udpframe->length = (uint16_t) (pNbuf->length + UDP_HDR_SIZE);
/* No checksum calcualation needed */
udpframe->chksum = (uint16_t) 0;
/* Add the length of the UDP packet to the total length of the packet */
pNbuf->length += 8;
myip = ip_get_myip(nif_get_protocol_info(nif, ETH_FRM_IP));
dbg("%s: sent UDP request to %d.%d.%d.%d from %d.%d.%d.%d\r\n", __FUNCTION__,
dest[0], dest[1], dest[2], dest[3],
myip[0], myip[1], myip[2], myip[3]);
return (ip_send(nif, dest, myip, IP_PROTO_UDP, pNbuf));
}
void udp_handler(NIF *nif, NBUF *pNbuf)
{
/*
* This function handles incoming UDP packets
*/
udp_frame_hdr *udpframe;
void (*handler)(NIF *, NBUF *);
udpframe = (udp_frame_hdr *) &pNbuf->data[pNbuf->offset];
dbg("%s: packet received\r\n", __FUNCTION__);
/*
* Adjust the length and valid data offset of the packet we are
* passing on
*/
pNbuf->length -= UDP_HDR_SIZE;
pNbuf->offset += UDP_HDR_SIZE;
/*
* Traverse the list of bound ports to see if there is a higher
* level protocol to pass the packet on to
*/
if ((handler = (void(*)(NIF*, NBUF*)) udp_port_handler(UDP_DEST(udpframe))) != NULL)
handler(nif, pNbuf);
else
{
dbg("%s: received UDP packet for non-supported port\n", __FUNCTION__);
nbuf_free(pNbuf);
}
return;
}