Contiki 2.6

simple-udp.c

00001 /**
00002  * \addtogroup simple-udp
00003  * @{
00004  */
00005 
00006 
00007 /*
00008  * Copyright (c) 2011, Swedish Institute of Computer Science.
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  * 2. Redistributions in binary form must reproduce the above copyright
00017  *    notice, this list of conditions and the following disclaimer in the
00018  *    documentation and/or other materials provided with the distribution.
00019  * 3. Neither the name of the Institute nor the names of its contributors
00020  *    may be used to endorse or promote products derived from this software
00021  *    without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00024  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00027  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00028  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00029  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00032  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00033  * SUCH DAMAGE.
00034  *
00035  * This file is part of the Contiki operating system.
00036  *
00037  * \file
00038  *         Header file for the simple-udp module.
00039  * \author
00040  *         Adam Dunkels <adam@sics.se>
00041  *
00042  */
00043 
00044 #include "contiki-net.h"
00045 #include "net/simple-udp.h"
00046 
00047 #include <string.h>
00048 
00049 
00050 PROCESS(simple_udp_process, "Simple UDP process");
00051 static uint8_t started = 0;
00052 static uint8_t databuffer[UIP_BUFSIZE];
00053 
00054 #define UIP_IP_BUF   ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
00055 
00056 /*---------------------------------------------------------------------------*/
00057 static void
00058 init_simple_udp(void)
00059 {
00060   if(started == 0) {
00061     process_start(&simple_udp_process, NULL);
00062     started = 1;
00063   }
00064 }
00065 /*---------------------------------------------------------------------------*/
00066 /**
00067  * \brief      Send a UDP packet
00068  * \param c    A pointer to a struct simple_udp_connection
00069  * \param data A pointer to the data to be sent
00070  * \param datalen The length of the data
00071  *
00072  *             This function sends a UDP packet. The packet will be
00073  *             sent to the IP address and with the UDP ports that were
00074  *             specified when the connection wa registered with
00075  *             simple_udp_register().
00076  *
00077  * \sa simple_udp_sendto()
00078  */
00079 int
00080 simple_udp_send(struct simple_udp_connection *c,
00081                 const void *data, uint16_t datalen)
00082 {
00083   if(c->udp_conn != NULL) {
00084     uip_udp_packet_sendto(c->udp_conn, data, datalen,
00085                           &c->remote_addr, UIP_HTONS(c->remote_port));
00086   }
00087   return 0;
00088 }
00089 /*---------------------------------------------------------------------------*/
00090 /**
00091  * \brief      Send a UDP packet to a specified IP address
00092  * \param c    A pointer to a struct simple_udp_connection
00093  * \param data A pointer to the data to be sent
00094  * \param datalen The length of the data
00095  * \param to   The IP address of the receiver
00096  *
00097  *             This function sends a UDP packet to a specified IP
00098  *             address. The packet will be sent with the UDP ports
00099  *             that were specified when the connection wa registered
00100  *             with simple_udp_register().
00101  *
00102  * \sa simple_udp_send()
00103  */
00104 int
00105 simple_udp_sendto(struct simple_udp_connection *c,
00106                   const void *data, uint16_t datalen,
00107                   const uip_ipaddr_t *to)
00108 {
00109   if(c->udp_conn != NULL) {
00110     uip_udp_packet_sendto(c->udp_conn, data, datalen,
00111                           to, UIP_HTONS(c->remote_port));
00112   }
00113   return 0;
00114 }
00115 /*---------------------------------------------------------------------------*/
00116 /**
00117  * \brief      Register a UDP connection
00118  * \param c    A pointer to a struct simple_udp_connection
00119  * \param local_port The local UDP port in host byte order
00120  * \param remote_addr The remote IP address
00121  * \param remote_port The remote UDP port in host byte order
00122  * \param receive_callback A pointer to a function to be called for incoming packets
00123  * \retval 0   If no UDP connection could be allocated
00124  * \retval 1   If the connection was successfully allocated
00125  *
00126  *             This function registers a UDP connection and attaches a
00127  *             callback function to it. The callback function will be
00128  *             called for incoming packets. The local UDP port can be
00129  *             set to 0 to indicate that an ephemeral UDP port should
00130  *             be allocated. The remote IP address can be NULL, to
00131  *             indicate that packets from any IP address should be
00132  *             accepted.
00133  *
00134  */
00135 int
00136 simple_udp_register(struct simple_udp_connection *c,
00137                     uint16_t local_port,
00138                     uip_ipaddr_t *remote_addr,
00139                     uint16_t remote_port,
00140                     simple_udp_callback receive_callback)
00141 {
00142 
00143   init_simple_udp();
00144 
00145   c->local_port = local_port;
00146   c->remote_port = remote_port;
00147   if(remote_addr != NULL) {
00148     uip_ipaddr_copy(&c->remote_addr, remote_addr);
00149   }
00150   c->receive_callback = receive_callback;
00151 
00152   PROCESS_CONTEXT_BEGIN(&simple_udp_process);
00153   c->udp_conn = udp_new(remote_addr, UIP_HTONS(remote_port), c);
00154   if(c->udp_conn != NULL) {
00155     udp_bind(c->udp_conn, UIP_HTONS(local_port));
00156   }
00157   PROCESS_CONTEXT_END();
00158 
00159   if(c->udp_conn == NULL) {
00160     return 0;
00161   }
00162   return 1;
00163 }
00164 /*---------------------------------------------------------------------------*/
00165 PROCESS_THREAD(simple_udp_process, ev, data)
00166 {
00167   struct simple_udp_connection *c;
00168   PROCESS_BEGIN();
00169   
00170   while(1) {
00171     PROCESS_WAIT_EVENT();
00172     if(ev == tcpip_event) {
00173 
00174       /* An appstate pointer is passed to use from the IP stack
00175          through the 'data' pointer. We registered this appstate when
00176          we did the udp_new() call in simple_udp_register() as the
00177          struct simple_udp_connection pointer. So we extract this
00178          pointer and use it when calling the reception callback. */
00179       c = (struct simple_udp_connection *)data;
00180 
00181       /* Defensive coding: although the appstate *should* be non-null
00182          here, we make sure to avoid the program crashing on us. */
00183       if(c != NULL) {
00184 
00185         /* If we were called because of incoming data, we should call
00186            the reception callback. */
00187         if(uip_newdata()) {
00188           /* Copy the data from the uIP data buffer into our own
00189              buffer to avoid the uIP buffer being messed with by the
00190              callee. */
00191           memcpy(databuffer, uip_appdata, uip_datalen());
00192 
00193           /* Call the client process. We use the PROCESS_CONTEXT
00194              mechanism to temporarily switch process context to the
00195              client process. */
00196           if(c->receive_callback != NULL) {
00197             PROCESS_CONTEXT_BEGIN(c->client_process);
00198             c->receive_callback(c,
00199                                 &(UIP_IP_BUF->srcipaddr),
00200                                 UIP_HTONS(UIP_IP_BUF->srcport),
00201                                 &(UIP_IP_BUF->destipaddr),
00202                                 UIP_HTONS(UIP_IP_BUF->destport),
00203                                 databuffer, uip_datalen());
00204             PROCESS_CONTEXT_END();
00205           }
00206         }
00207       }
00208     }
00209 
00210   }
00211 
00212   PROCESS_END();
00213 }
00214 /*---------------------------------------------------------------------------*/
00215 /** @} */