forked from contiki-os/contiki
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A significantly simpler API for sending UDP packets
- Loading branch information
Adam Dunkels
committed
Aug 29, 2011
1 parent
4fee151
commit 7ce313e
Showing
2 changed files
with
306 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
/** | ||
* \addtogroup simple-udp | ||
* @{ | ||
*/ | ||
|
||
|
||
/* | ||
* Copyright (c) 2011, Swedish Institute of Computer Science. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* 1. Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* 2. Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* 3. Neither the name of the Institute nor the names of its contributors | ||
* may be used to endorse or promote products derived from this software | ||
* without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND | ||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE | ||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
* SUCH DAMAGE. | ||
* | ||
* This file is part of the Contiki operating system. | ||
* | ||
* \file | ||
* Header file for the simple-udp module. | ||
* \author | ||
* Adam Dunkels <[email protected]> | ||
* | ||
*/ | ||
|
||
#include "simple-udp.h" | ||
#include "contiki-net.h" | ||
|
||
PROCESS(simple_udp_process, "Simple UDP process"); | ||
static uint8_t started = 0; | ||
static uint8_t databuffer[UIP_BUFSIZE]; | ||
|
||
#define UIP_IP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) | ||
|
||
/*---------------------------------------------------------------------------*/ | ||
static void | ||
init_simple_udp(void) | ||
{ | ||
if(started == 0) { | ||
process_start(&simple_udp_process, NULL); | ||
started = 1; | ||
} | ||
} | ||
/*---------------------------------------------------------------------------*/ | ||
/** | ||
* \brief Send a UDP packet | ||
* \param c A pointer to a struct simple_udp_connection | ||
* \param data A pointer to the data to be sent | ||
* \param datalen The length of the data | ||
* | ||
* This function sends a UDP packet. The packet will be | ||
* sent to the IP address and with the UDP ports that were | ||
* specified when the connection wa registered with | ||
* simple_udp_register(). | ||
* | ||
* \sa simple_udp_sendto() | ||
*/ | ||
int | ||
simple_udp_send(struct simple_udp_connection *c, | ||
const void *data, uint16_t datalen) | ||
{ | ||
if(c->udp_conn != NULL) { | ||
uip_udp_packet_sendto(c->udp_conn, data, datalen, | ||
&c->remote_addr, UIP_HTONS(c->remote_port)); | ||
} | ||
return 0; | ||
} | ||
/*---------------------------------------------------------------------------*/ | ||
/** | ||
* \brief Send a UDP packet to a specified IP address | ||
* \param c A pointer to a struct simple_udp_connection | ||
* \param data A pointer to the data to be sent | ||
* \param datalen The length of the data | ||
* \param to The IP address of the receiver | ||
* | ||
* This function sends a UDP packet to a specified IP | ||
* address. The packet will be sent with the UDP ports | ||
* that were specified when the connection wa registered | ||
* with simple_udp_register(). | ||
* | ||
* \sa simple_udp_send() | ||
*/ | ||
int | ||
simple_udp_sendto(struct simple_udp_connection *c, | ||
const void *data, uint16_t datalen, | ||
const uip_ipaddr_t *to) | ||
{ | ||
if(c->udp_conn != NULL) { | ||
uip_udp_packet_sendto(c->udp_conn, data, datalen, | ||
to, UIP_HTONS(c->remote_port)); | ||
} | ||
return 0; | ||
} | ||
/*---------------------------------------------------------------------------*/ | ||
/** | ||
* \brief Register a UDP connection | ||
* \param c A pointer to a struct simple_udp_connection | ||
* \param local_port The local UDP port in host byte order | ||
* \param remote_addr The remote IP address | ||
* \param remote_port The remote UDP port in host byte order | ||
* \param receive_callback A pointer to a function to be called for incoming packets | ||
* \retval 0 If no UDP connection could be allocated | ||
* \retval 1 If the connection was successfully allocated | ||
* | ||
* This function registers a UDP connection and attaches a | ||
* callback function to it. The callback function will be | ||
* called for incoming packets. The local UDP port can be | ||
* set to 0 to indicate that an ephemeral UDP port should | ||
* be allocated. The remote IP address can be NULL, to | ||
* indicate that packets from any IP address should be | ||
* accepted. | ||
* | ||
*/ | ||
int | ||
simple_udp_register(struct simple_udp_connection *c, | ||
uint16_t local_port, | ||
uip_ipaddr_t *remote_addr, | ||
uint16_t remote_port, | ||
simple_udp_callback receive_callback) | ||
{ | ||
|
||
init_simple_udp(); | ||
|
||
c->local_port = local_port; | ||
c->remote_port = remote_port; | ||
if(remote_addr != NULL) { | ||
uip_ipaddr_copy(&c->remote_addr, remote_addr); | ||
} | ||
c->receive_callback = receive_callback; | ||
|
||
PROCESS_CONTEXT_BEGIN(&simple_udp_process); | ||
c->udp_conn = udp_new(remote_addr, UIP_HTONS(remote_port), c); | ||
if(c->udp_conn != NULL) { | ||
udp_bind(c->udp_conn, UIP_HTONS(local_port)); | ||
} | ||
PROCESS_CONTEXT_END(); | ||
|
||
if(c->udp_conn == NULL) { | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
/*---------------------------------------------------------------------------*/ | ||
PROCESS_THREAD(simple_udp_process, ev, data) | ||
{ | ||
struct simple_udp_connection *c; | ||
PROCESS_BEGIN(); | ||
|
||
while(1) { | ||
PROCESS_WAIT_EVENT(); | ||
if(ev == tcpip_event) { | ||
|
||
/* An appstate pointer is passed to use from the IP stack | ||
through the 'data' pointer. We registered this appstate when | ||
we did the udp_new() call in simple_udp_register() as the | ||
struct simple_udp_connection pointer. So we extract this | ||
pointer and use it when calling the reception callback. */ | ||
c = (struct simple_udp_connection *)data; | ||
|
||
/* Defensive coding: although the appstate *should* be non-null | ||
here, we make sure to avoid the program crashing on us. */ | ||
if(c != NULL) { | ||
|
||
/* If we were called because of incoming data, we should call | ||
the reception callback. */ | ||
if(uip_newdata()) { | ||
/* Copy the data from the uIP data buffer into our own | ||
buffer to avoid the uIP buffer being messed with by the | ||
callee. */ | ||
memcpy(databuffer, uip_appdata, uip_datalen()); | ||
|
||
/* Call the client process. We use the PROCESS_CONTEXT | ||
mechanism to temporarily switch process context to the | ||
client process. */ | ||
if(c->receive_callback != NULL) { | ||
PROCESS_CONTEXT_BEGIN(c->client_process); | ||
c->receive_callback(c, | ||
&(UIP_IP_BUF->srcipaddr), | ||
UIP_HTONS(UIP_IP_BUF->srcport), | ||
&(UIP_IP_BUF->destipaddr), | ||
UIP_HTONS(UIP_IP_BUF->destport), | ||
databuffer, uip_datalen()); | ||
PROCESS_CONTEXT_END(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
PROCESS_END(); | ||
} | ||
/*---------------------------------------------------------------------------*/ | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/** | ||
* \addtogroup uip | ||
* @{ | ||
*/ | ||
|
||
|
||
/** | ||
* \defgroup simple-udp | ||
* | ||
* The default Contiki UDP API is difficult to use. The simple-udp | ||
* module provides a significantly simpler API. | ||
* | ||
* @{ | ||
*/ | ||
|
||
/* | ||
* Copyright (c) 2011, Swedish Institute of Computer Science. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* 1. Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* 2. Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in the | ||
* documentation and/or other materials provided with the distribution. | ||
* 3. Neither the name of the Institute nor the names of its contributors | ||
* may be used to endorse or promote products derived from this software | ||
* without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND | ||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE | ||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
* SUCH DAMAGE. | ||
* | ||
* This file is part of the Contiki operating system. | ||
* | ||
* \file | ||
* Header file for the simple-udp module. | ||
* \author | ||
* Adam Dunkels <[email protected]> | ||
* | ||
*/ | ||
|
||
#ifndef SIMPLE_UDP_H | ||
#define SIMPLE_UDP_H | ||
|
||
#include "net/uip.h" | ||
|
||
struct simple_udp_connection; | ||
|
||
typedef void (* simple_udp_callback)(struct simple_udp_connection *c, | ||
const uip_ipaddr_t *source_addr, | ||
uint16_t source_port, | ||
const uip_ipaddr_t *dest_addr, | ||
uint16_t dest_port, | ||
const uint8_t *data, uint16_t datalen); | ||
|
||
struct simple_udp_connection { | ||
struct simple_udp_connection *next; | ||
uip_ipaddr_t remote_addr; | ||
uint16_t remote_port, local_port; | ||
simple_udp_callback receive_callback; | ||
struct uip_udp_conn *udp_conn; | ||
struct process *client_process; | ||
}; | ||
|
||
int simple_udp_register(struct simple_udp_connection *c, | ||
uint16_t local_port, | ||
uip_ipaddr_t *remote_addr, | ||
uint16_t remote_port, | ||
simple_udp_callback receive_callback); | ||
|
||
int simple_udp_send(struct simple_udp_connection *c, | ||
const void *data, uint16_t datalen); | ||
|
||
int simple_udp_sendto(struct simple_udp_connection *c, | ||
const void *data, uint16_t datalen, | ||
const uip_ipaddr_t *to); | ||
|
||
void simple_udp_init(void); | ||
|
||
#endif /* SIMPLE_UDP_H */ | ||
|
||
/** @} */ | ||
/** @} */ |