diff --git a/examples/udp-ipv6/Makefile b/examples/udp-ipv6/Makefile new file mode 100644 index 000000000..fbec78d44 --- /dev/null +++ b/examples/udp-ipv6/Makefile @@ -0,0 +1,8 @@ +all: udp-server udp-client +DEFAULT_TARGET=minimal-net + +UIP_CONF_IPV6=1 +DEFINES=WITH_UIP6 + +CONTIKI = ../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/udp-ipv6/udp-client.c b/examples/udp-ipv6/udp-client.c new file mode 100644 index 000000000..04b6aad7e --- /dev/null +++ b/examples/udp-ipv6/udp-client.c @@ -0,0 +1,159 @@ +/* + * 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. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#define PRINTLLADDR(addr) +#endif + +#define SEND_INTERVAL 15 * CLOCK_SECOND +#define MAX_PAYLOAD_LEN 40 + +static struct uip_udp_conn *client_conn; +/*---------------------------------------------------------------------------*/ +PROCESS(udp_client_process, "UDP client process"); +AUTOSTART_PROCESSES(&udp_client_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + char *str; + + if(uip_newdata()) { + str = uip_appdata; + str[uip_datalen()] = '\0'; + printf("Response from the server: '%s'\n", str); + } +} +/*---------------------------------------------------------------------------*/ +static void +timeout_handler(void) +{ + static int seq_id; + char buf[MAX_PAYLOAD_LEN]; + + printf("Client sending to: "); + PRINT6ADDR(&client_conn->ripaddr); + sprintf(buf, "Hello %d from the client", ++seq_id); + printf(" (msg: %s)\n", buf); + uip_udp_packet_send(client_conn, buf, strlen(buf)); +} +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uip_netif_state state; + + PRINTF("Client IPv6 addresses: "); + for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; i++) { + state = uip_netif_physical_if.addresses[i].state; + if(state == TENTATIVE || state == PREFERRED) { + PRINT6ADDR(&uip_netif_physical_if.addresses[i].ipaddr); + PRINTF("\n"); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_netif_addr_autoconf_set(&ipaddr, &uip_lladdr); + uip_netif_addr_add(&ipaddr, 16, 0, TENTATIVE); +} +/*---------------------------------------------------------------------------*/ +static void +set_connection_address(uip_ipaddr_t *ipaddr) +{ +#ifdef UDP_ADDR_A + uip_ip6addr(ipaddr, + UDP_ADDR_A,UDP_ADDR_B,UDP_ADDR_C,UDP_ADDR_D, + UDP_ADDR_E,UDP_ADDR_F,UDP_ADDR_G,UDP_ADDR_H); +#elif UIP_CONF_ROUTER + uip_ip6addr(ipaddr,0xaaaa,0,0,0,0x0212,0x7504,0x0004,0x0404); +#else + uip_ip6addr(ipaddr,0xfe80,0,0,0,0x6466,0x6666,0x6666,0x6666); +#endif /* UDP_ADDR_A */ +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_client_process, ev, data) +{ + static struct etimer et; + uip_ipaddr_t ipaddr; + + PROCESS_BEGIN(); + PRINTF("UDP client process started\n"); + +#if UIP_CONF_ROUTER + set_global_address(); +#endif + + print_local_addresses(); + + set_connection_address(&ipaddr); + + /* new connection with remote host */ + client_conn = udp_new(&ipaddr, HTONS(3000), NULL); + udp_bind(client_conn, HTONS(3001)); + + PRINTF("Created a connection with the server "); + PRINT6ADDR(&client_conn->ripaddr); + PRINTF("local/remote port %u/%u\n", + HTONS(client_conn->lport), HTONS(client_conn->rport)); + + etimer_set(&et, SEND_INTERVAL); + while(1) { + PROCESS_YIELD(); + if(etimer_expired(&et)) { + timeout_handler(); + etimer_restart(&et); + } else if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/udp-ipv6/udp-server.c b/examples/udp-ipv6/udp-server.c new file mode 100644 index 000000000..ac5b97eac --- /dev/null +++ b/examples/udp-ipv6/udp-server.c @@ -0,0 +1,128 @@ +/* + * 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. + * + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" + +#include + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#define PRINTLLADDR(addr) +#endif + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#define MAX_PAYLOAD_LEN 120 + +static struct uip_udp_conn *server_conn; + +PROCESS(udp_server_process, "UDP server process"); +AUTOSTART_PROCESSES(&udp_server_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + static int seq_id; + char buf[MAX_PAYLOAD_LEN]; + + if(uip_newdata()) { + ((char *)uip_appdata)[uip_datalen()] = 0; + PRINTF("Server received: '%s' from ", (char *)uip_appdata); + PRINT6ADDR(&server_conn->ripaddr); + PRINTF("\n"); + + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + PRINTF("Responding with message: "); + sprintf(buf, "Hello from the server! (%d)", ++seq_id); + PRINTF("%s\n", buf); + + uip_udp_packet_send(server_conn, buf, strlen(buf)); + /* Restore server connection to allow data from any node */ + memset(&server_conn->ripaddr, 0, sizeof(server_conn->ripaddr)); + } +} +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uip_netif_state state; + + PRINTF("Server IPv6 addresses: "); + for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; i++) { + state = uip_netif_physical_if.addresses[i].state; + if(state == TENTATIVE || state == PREFERRED) { + PRINT6ADDR(&uip_netif_physical_if.addresses[i].ipaddr); + PRINTF("\n"); + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_server_process, ev, data) +{ + uip_ipaddr_t ipaddr; + + PROCESS_BEGIN(); + PRINTF("UDP server started\n"); + +#if UIP_CONF_ROUTER + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_netif_addr_autoconf_set(&ipaddr, &uip_lladdr); + uip_netif_addr_add(&ipaddr, 16, 0, TENTATIVE); +#endif /* UIP_CONF_ROUTER */ + + print_local_addresses(); + + server_conn = udp_new(NULL, HTONS(3001), NULL); + udp_bind(server_conn, HTONS(3000)); + + PRINTF("Created a server connection with remote address "); + PRINT6ADDR(&server_conn->ripaddr); + PRINTF("local/remote port %u/%u\n", HTONS(server_conn->lport), + HTONS(server_conn->rport)); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/