Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
a824722862
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -24,6 +24,7 @@
|
|||
*.c128
|
||||
*.c64
|
||||
*.cc2538dk
|
||||
*.srf06-cc26xx
|
||||
*.ev-aducrf101mkxz
|
||||
*.report
|
||||
summary
|
||||
|
|
|
@ -48,6 +48,13 @@ before_script:
|
|||
arm-none-eabi-gcc --version ;
|
||||
fi
|
||||
|
||||
## Download and extract cc26xxware
|
||||
- if [ ${BUILD_ARCH:-0} = arm ] ; then
|
||||
wget http://www.ti.com/lit/sw/swrc296/swrc296.zip &&
|
||||
unzip swrc296.zip &&
|
||||
export TI_CC26XXWARE=cc26xxware_2_20_06_14829 ;
|
||||
fi
|
||||
|
||||
## Install RL78 GCC toolchain
|
||||
- sudo apt-get install libncurses5:i386 zlib1g:i386
|
||||
- $WGET http://adamdunkels.github.io/contiki-fork/gnurl78-v13.02-elf_1-2_i386.deb &&
|
||||
|
@ -115,6 +122,6 @@ env:
|
|||
- BUILD_TYPE='compile-8051-ports' BUILD_CATEGORY='compile' BUILD_ARCH='8051'
|
||||
- BUILD_TYPE='compile-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs'
|
||||
- BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502'
|
||||
# - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm'
|
||||
- BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm'
|
||||
- BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja'
|
||||
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja'
|
||||
|
|
|
@ -88,7 +88,7 @@ makestrings(void)
|
|||
uip_getdraddr(&addr);
|
||||
makeaddr(&addr, gateway);
|
||||
|
||||
addrptr = resolv_getserver();
|
||||
addrptr = uip_nameserver_get(0);
|
||||
if(addrptr != NULL) {
|
||||
makeaddr(addrptr, dnsserver);
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ dhcpc_configured(const struct dhcpc_state *s)
|
|||
uip_sethostaddr(&s->ipaddr);
|
||||
uip_setnetmask(&s->netmask);
|
||||
uip_setdraddr(&s->default_router);
|
||||
resolv_conf(&s->dnsaddr);
|
||||
uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME);
|
||||
set_statustext("Configured.");
|
||||
process_post(PROCESS_CURRENT(), SHOWCONFIG, NULL);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c er-coap-observe.c er-coap-separate.c er-coap-res-well-known-core.c er-coap-block1.c
|
||||
er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c \
|
||||
er-coap-observe.c er-coap-separate.c er-coap-res-well-known-core.c \
|
||||
er-coap-block1.c er-coap-observe-client.c
|
||||
|
||||
# Erbium will implement the REST Engine
|
||||
CFLAGS += -DREST=coap_rest_implementation
|
||||
|
|
|
@ -253,6 +253,16 @@ coap_receive(void)
|
|||
}
|
||||
/* if(ACKed transaction) */
|
||||
transaction = NULL;
|
||||
|
||||
#if COAP_OBSERVE_CLIENT
|
||||
/* if observe notification */
|
||||
if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON)
|
||||
&& IS_OPTION(message, COAP_OPTION_OBSERVE)) {
|
||||
PRINTF("Observe [%u]\n", message->observe);
|
||||
coap_handle_notification(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
|
||||
message);
|
||||
}
|
||||
#endif /* COAP_OBSERVE_CLIENT */
|
||||
} /* request or response */
|
||||
} /* parsed correctly */
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "er-coap-transactions.h"
|
||||
#include "er-coap-observe.h"
|
||||
#include "er-coap-separate.h"
|
||||
#include "er-coap-observe-client.h"
|
||||
|
||||
#define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT)
|
||||
|
||||
|
|
342
apps/er-coap/er-coap-observe-client.c
Normal file
342
apps/er-coap/er-coap-observe-client.c
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Daniele Alessandrelli.
|
||||
* 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
|
||||
* Extension to Erbium for enabling CoAP observe clients
|
||||
* \author
|
||||
* Daniele Alessandrelli <daniele.alessandrelli@gmail.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "er-coap.h"
|
||||
#include "er-coap-observe-client.h"
|
||||
|
||||
/* Compile this code only if client-side support for CoAP Observe is required */
|
||||
#if COAP_OBSERVE_CLIENT
|
||||
|
||||
#define DEBUG 1
|
||||
#if DEBUG
|
||||
#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]", \
|
||||
((uint8_t *)addr)[0], ((uint8_t *)addr)[1], \
|
||||
((uint8_t *)addr)[2], ((uint8_t *)addr)[3], \
|
||||
((uint8_t *)addr)[4], ((uint8_t *)addr)[5], \
|
||||
((uint8_t *)addr)[6], ((uint8_t *)addr)[7], \
|
||||
((uint8_t *)addr)[8], ((uint8_t *)addr)[9], \
|
||||
((uint8_t *)addr)[10], ((uint8_t *)addr)[11], \
|
||||
((uint8_t *)addr)[12], ((uint8_t *)addr)[13], \
|
||||
((uint8_t *)addr)[14], ((uint8_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
|
||||
|
||||
MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES);
|
||||
LIST(obs_subjects_list);
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static size_t
|
||||
get_token(void *packet, const uint8_t **token)
|
||||
{
|
||||
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
||||
|
||||
*token = coap_pkt->token;
|
||||
|
||||
return coap_pkt->token_len;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int
|
||||
set_token(void *packet, const uint8_t *token, size_t token_len)
|
||||
{
|
||||
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
|
||||
|
||||
coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
|
||||
memcpy(coap_pkt->token, token, coap_pkt->token_len);
|
||||
|
||||
return coap_pkt->token_len;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
coap_observee_t *
|
||||
coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port,
|
||||
const uint8_t *token, size_t token_len, const char *url,
|
||||
notification_callback_t notification_callback,
|
||||
void *data)
|
||||
{
|
||||
coap_observee_t *o;
|
||||
|
||||
/* Remove existing observe relationship, if any. */
|
||||
coap_obs_remove_observee_by_url(addr, port, url);
|
||||
o = memb_alloc(&obs_subjects_memb);
|
||||
if(o) {
|
||||
o->url = url;
|
||||
uip_ipaddr_copy(&o->addr, addr);
|
||||
o->port = port;
|
||||
o->token_len = token_len;
|
||||
memcpy(o->token, token, token_len);
|
||||
/* o->last_mid = 0; */
|
||||
o->notification_callback = notification_callback;
|
||||
o->data = data;
|
||||
/* stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); */
|
||||
PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
|
||||
o->token[1]);
|
||||
list_add(obs_subjects_list, o);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_obs_remove_observee(coap_observee_t *o)
|
||||
{
|
||||
PRINTF("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0],
|
||||
o->token[1]);
|
||||
memb_free(&obs_subjects_memb, o);
|
||||
list_remove(obs_subjects_list, o);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
coap_observee_t *
|
||||
coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len)
|
||||
{
|
||||
coap_observee_t *obs = NULL;
|
||||
|
||||
for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs;
|
||||
obs = obs->next) {
|
||||
PRINTF("Looking for token 0x%02X%02X\n", token[0], token[1]);
|
||||
if(obs->token_len == token_len
|
||||
&& memcmp(obs->token, token, token_len) == 0) {
|
||||
return obs;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
|
||||
uint8_t *token, size_t token_len)
|
||||
{
|
||||
int removed = 0;
|
||||
coap_observee_t *obs = NULL;
|
||||
|
||||
for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs;
|
||||
obs = obs->next) {
|
||||
PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]);
|
||||
if(uip_ipaddr_cmp(&obs->addr, addr)
|
||||
&& obs->port == port
|
||||
&& obs->token_len == token_len
|
||||
&& memcmp(obs->token, token, token_len) == 0) {
|
||||
coap_obs_remove_observee(obs);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int
|
||||
coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
|
||||
const char *url)
|
||||
{
|
||||
int removed = 0;
|
||||
coap_observee_t *obs = NULL;
|
||||
|
||||
for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs;
|
||||
obs = obs->next) {
|
||||
PRINTF("Remove check URL %s\n", url);
|
||||
if(uip_ipaddr_cmp(&obs->addr, addr)
|
||||
&& obs->port == port
|
||||
&& (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) {
|
||||
coap_obs_remove_observee(obs);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void
|
||||
simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port,
|
||||
coap_packet_t *notification)
|
||||
{
|
||||
static coap_packet_t response[1];
|
||||
size_t len;
|
||||
|
||||
coap_init_message(response, type, NO_ERROR, notification->mid);
|
||||
len = coap_serialize_message(response, uip_appdata);
|
||||
coap_send_message(addr, port, uip_appdata, len);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static coap_notification_flag_t
|
||||
classify_notification(void *response, int first)
|
||||
{
|
||||
coap_packet_t *pkt;
|
||||
|
||||
pkt = (coap_packet_t *)response;
|
||||
if(!pkt) {
|
||||
PRINTF("no response\n");
|
||||
return NO_REPLY_FROM_SERVER;
|
||||
}
|
||||
PRINTF("server replied\n");
|
||||
if(!IS_RESPONSE_CODE_2_XX(pkt)) {
|
||||
PRINTF("error response code\n");
|
||||
return ERROR_RESPONSE_CODE;
|
||||
}
|
||||
if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) {
|
||||
PRINTF("server does not support observe\n");
|
||||
return OBSERVE_NOT_SUPPORTED;
|
||||
}
|
||||
if(first) {
|
||||
return OBSERVE_OK;
|
||||
}
|
||||
return NOTIFICATION_OK;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
|
||||
coap_packet_t *notification)
|
||||
{
|
||||
coap_packet_t *pkt;
|
||||
const uint8_t *token;
|
||||
int token_len;
|
||||
coap_observee_t *obs;
|
||||
coap_notification_flag_t flag;
|
||||
uint32_t observe;
|
||||
|
||||
PRINTF("coap_handle_notification()\n");
|
||||
pkt = (coap_packet_t *)notification;
|
||||
token_len = get_token(pkt, &token);
|
||||
PRINTF("Getting token\n");
|
||||
if(0 == token_len) {
|
||||
PRINTF("Error while handling coap observe notification: "
|
||||
"no token in message\n");
|
||||
return;
|
||||
}
|
||||
PRINTF("Getting observee info\n");
|
||||
obs = coap_get_obs_subject_by_token(token, token_len);
|
||||
if(NULL == obs) {
|
||||
PRINTF("Error while handling coap observe notification: "
|
||||
"no matching token found\n");
|
||||
simple_reply(COAP_TYPE_RST, addr, port, notification);
|
||||
return;
|
||||
}
|
||||
if(notification->type == COAP_TYPE_CON) {
|
||||
simple_reply(COAP_TYPE_ACK, addr, port, notification);
|
||||
}
|
||||
if(obs->notification_callback != NULL) {
|
||||
flag = classify_notification(notification, 0);
|
||||
/* TODO: the following mechanism for discarding duplicates is too trivial */
|
||||
/* refer to Observe RFC for a better solution */
|
||||
if(flag == NOTIFICATION_OK) {
|
||||
coap_get_header_observe(notification, &observe);
|
||||
if(observe == obs->last_observe) {
|
||||
PRINTF("Discarding duplicate\n");
|
||||
return;
|
||||
}
|
||||
obs->last_observe = observe;
|
||||
}
|
||||
obs->notification_callback(obs, notification, flag);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void
|
||||
handle_obs_registration_response(void *data, void *response)
|
||||
{
|
||||
coap_observee_t *obs;
|
||||
notification_callback_t notification_callback;
|
||||
coap_notification_flag_t flag;
|
||||
|
||||
PRINTF("handle_obs_registration_response(): ");
|
||||
obs = (coap_observee_t *)data;
|
||||
notification_callback = obs->notification_callback;
|
||||
flag = classify_notification(response, 1);
|
||||
if(notification_callback) {
|
||||
notification_callback(obs, response, flag);
|
||||
}
|
||||
if(flag != OBSERVE_OK) {
|
||||
coap_obs_remove_observee(obs);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint8_t
|
||||
coap_generate_token(uint8_t **token_ptr)
|
||||
{
|
||||
static uint8_t token = 0;
|
||||
|
||||
token++;
|
||||
/* FIXME: we should check that this token is not already used */
|
||||
*token_ptr = (uint8_t *)&token;
|
||||
return sizeof(token);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
coap_observee_t *
|
||||
coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri,
|
||||
notification_callback_t notification_callback,
|
||||
void *data)
|
||||
{
|
||||
coap_packet_t request[1];
|
||||
coap_transaction_t *t;
|
||||
uint8_t *token;
|
||||
uint8_t token_len;
|
||||
coap_observee_t *obs;
|
||||
|
||||
obs = NULL;
|
||||
coap_init_message(request, COAP_TYPE_CON, COAP_GET, coap_get_mid());
|
||||
coap_set_header_uri_path(request, uri);
|
||||
coap_set_header_observe(request, 0);
|
||||
token_len = coap_generate_token(&token);
|
||||
set_token(request, token, token_len);
|
||||
t = coap_new_transaction(request->mid, addr, port);
|
||||
if(t) {
|
||||
obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri,
|
||||
notification_callback, data);
|
||||
if(obs) {
|
||||
t->callback = handle_obs_registration_response;
|
||||
t->callback_data = obs;
|
||||
t->packet_len = coap_serialize_message(request, t->packet);
|
||||
coap_send_transaction(t);
|
||||
} else {
|
||||
PRINTF("Could not allocate obs_subject resource buffer");
|
||||
coap_clear_transaction(t);
|
||||
}
|
||||
} else {
|
||||
PRINTF("Could not allocate transaction buffer");
|
||||
}
|
||||
return obs;
|
||||
}
|
||||
#endif /* COAP_OBSERVE_CLIENT */
|
121
apps/er-coap/er-coap-observe-client.h
Normal file
121
apps/er-coap/er-coap-observe-client.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Daniele Alessandrelli.
|
||||
* 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
|
||||
* Extension to Erbium for enabling CoAP observe clients
|
||||
* \author
|
||||
* Daniele Alessandrelli <daniele.alessandrelli@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef COAP_OBSERVING_CLIENT_H_
|
||||
#define COAP_OBSERVING_CLIENT_H_
|
||||
|
||||
#include "er-coap.h"
|
||||
#include "er-coap-transactions.h"
|
||||
|
||||
#ifndef COAP_OBSERVE_CLIENT
|
||||
#define COAP_OBSERVE_CLIENT 0
|
||||
#endif
|
||||
|
||||
#ifdef COAP_CONF_MAX_OBSERVEES
|
||||
#define COAP_MAX_OBSERVEES COAP_CONF_MAX_OBSERVEES
|
||||
#else
|
||||
#define COAP_MAX_OBSERVEES 4
|
||||
#endif /* COAP_CONF_MAX_OBSERVEES */
|
||||
|
||||
#if COAP_MAX_OPEN_TRANSACTIONS < COAP_MAX_OBSERVEES
|
||||
#warning "COAP_MAX_OPEN_TRANSACTIONS smaller than COAP_MAX_OBSERVEES: " \
|
||||
"this may be a problem"
|
||||
#endif
|
||||
|
||||
#define IS_RESPONSE_CODE_2_XX(message) (64 < message->code \
|
||||
&& message->code < 128)
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
typedef enum {
|
||||
OBSERVE_OK,
|
||||
NOTIFICATION_OK,
|
||||
OBSERVE_NOT_SUPPORTED,
|
||||
ERROR_RESPONSE_CODE,
|
||||
NO_REPLY_FROM_SERVER,
|
||||
} coap_notification_flag_t;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
typedef struct coap_observee_s coap_observee_t;
|
||||
|
||||
typedef void (*notification_callback_t)(coap_observee_t *subject,
|
||||
void *notification,
|
||||
coap_notification_flag_t);
|
||||
|
||||
struct coap_observee_s {
|
||||
coap_observee_t *next; /* for LIST */
|
||||
uip_ipaddr_t addr;
|
||||
uint16_t port;
|
||||
const char *url;
|
||||
uint8_t token_len;
|
||||
uint8_t token[COAP_TOKEN_LEN];
|
||||
void *data; /* generic pointer for storing user data */
|
||||
notification_callback_t notification_callback;
|
||||
uint32_t last_observe;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
coap_observee_t *coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port,
|
||||
const uint8_t *token, size_t token_len,
|
||||
const char *url,
|
||||
notification_callback_t
|
||||
notification_callback, void *data);
|
||||
|
||||
void coap_obs_remove_observee(coap_observee_t *o);
|
||||
|
||||
coap_observee_t *coap_obs_get_observee_by_token(const uint8_t *token,
|
||||
size_t token_len);
|
||||
|
||||
int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
|
||||
uint8_t *token, size_t token_len);
|
||||
|
||||
int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
|
||||
const char *url);
|
||||
|
||||
void coap_handle_notification(uip_ipaddr_t *, uint16_t port,
|
||||
coap_packet_t *notification);
|
||||
|
||||
coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr,
|
||||
uint16_t port, char *uri,
|
||||
notification_callback_t
|
||||
notification_callback,
|
||||
void *data);
|
||||
/* TODO: this function may be moved to er-coap.c */
|
||||
uint8_t coap_generate_token(uint8_t **token_ptr);
|
||||
|
||||
#endif /* COAP_OBSERVING_CLIENT_H_ */
|
1
apps/mqtt/Makefile.mqtt
Normal file
1
apps/mqtt/Makefile.mqtt
Normal file
|
@ -0,0 +1 @@
|
|||
mqtt_src = mqtt.c
|
1484
apps/mqtt/mqtt.c
Normal file
1484
apps/mqtt/mqtt.c
Normal file
File diff suppressed because it is too large
Load diff
509
apps/mqtt/mqtt.h
Normal file
509
apps/mqtt/mqtt.h
Normal file
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/
|
||||
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \addtogroup apps
|
||||
* @{
|
||||
*
|
||||
* \defgroup mqtt-engine An implementation of MQTT v3.1
|
||||
* @{
|
||||
*
|
||||
* This application is an engine for MQTT v3.1. It supports QoS Levels 0 and 1.
|
||||
*
|
||||
* MQTT is a Client Server publish/subscribe messaging transport protocol.
|
||||
* It is light weight, open, simple, and designed so as to be easy to implement.
|
||||
* These characteristics make it ideal for use in many situations, including
|
||||
* constrained environments such as for communication in Machine to Machine
|
||||
* (M2M) and Internet of Things (IoT) contexts where a small code footprint is
|
||||
* required and/or network bandwidth is at a premium.
|
||||
*
|
||||
* The protocol runs over TCP/IP, more specifically tcp_socket.
|
||||
* Its features include:
|
||||
*
|
||||
* - Use of the publish/subscribe message pattern which provides
|
||||
* one-to-many message distribution and decoupling of applications.
|
||||
* - A messaging transport that is agnostic to the content of the payload.
|
||||
* Three qualities of service for message delivery:
|
||||
* -- "At most once" (0), where messages are delivered according to the best
|
||||
* efforts of the operating environment. Message loss can occur.
|
||||
* This level could be used, for example, with ambient sensor data where it
|
||||
* does not matter if an individual reading is lost as the next one will be
|
||||
* published soon after.
|
||||
* --"At least once" (1), where messages are assured to arrive but duplicates
|
||||
* can occur.
|
||||
* -- "Exactly once" (2), where message are assured to arrive exactly once.
|
||||
* This level could be used, for example, with billing systems where duplicate
|
||||
* or lost messages could lead to incorrect charges being applied. This QoS
|
||||
* level is currently not supported in this implementation.
|
||||
*
|
||||
* - A small transport overhead and protocol exchanges minimized to reduce
|
||||
* network traffic.
|
||||
* - A mechanism, Last Will, to notify interested parties when an abnormal
|
||||
* disconnection occurs.
|
||||
*
|
||||
* The protocol specification and other useful information can be found
|
||||
* here: http://mqtt.org
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Header file for the Contiki MQTT engine
|
||||
*
|
||||
* \author
|
||||
* Texas Instruments
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef MQTT_H_
|
||||
#define MQTT_H_
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "contiki-lib.h"
|
||||
#include "lib/random.h"
|
||||
#include "sys/ctimer.h"
|
||||
#include "sys/etimer.h"
|
||||
#include "net/rpl/rpl.h"
|
||||
#include "net/ip/uip.h"
|
||||
#include "net/ipv6/uip-ds6.h"
|
||||
#include "dev/leds.h"
|
||||
|
||||
#include "tcp-socket.h"
|
||||
#include "udp-socket.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Protocol constants */
|
||||
#define MQTT_CLIENT_ID_MAX_LEN 23
|
||||
|
||||
/* Size of the underlying TCP buffers */
|
||||
#define MQTT_TCP_INPUT_BUFF_SIZE 512
|
||||
#define MQTT_TCP_OUTPUT_BUFF_SIZE 512
|
||||
|
||||
#define MQTT_INPUT_BUFF_SIZE 512
|
||||
#define MQTT_MAX_TOPIC_LENGTH 64
|
||||
#define MQTT_MAX_TOPICS_PER_SUBSCRIBE 1
|
||||
|
||||
#define MQTT_FHDR_SIZE 1
|
||||
#define MQTT_MAX_REMAINING_LENGTH_BYTES 4
|
||||
#define MQTT_PROTOCOL_VERSION 3
|
||||
#define MQTT_PROTOCOL_NAME "MQIsdp"
|
||||
#define MQTT_TOPIC_MAX_LENGTH 128
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Debug configuration, this is similar but not exactly like the Debugging
|
||||
* System discussion at https://github.com/contiki-os/contiki/wiki.
|
||||
*/
|
||||
#define DEBUG_MQTT 0
|
||||
|
||||
#if DEBUG_MQTT == 1
|
||||
#define DBG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(...)
|
||||
#endif /* DEBUG */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
extern process_event_t mqtt_update_event;
|
||||
|
||||
/* Forward declaration */
|
||||
struct mqtt_connection;
|
||||
|
||||
typedef enum {
|
||||
MQTT_RETAIN_OFF,
|
||||
MQTT_RETAIN_ON,
|
||||
} mqtt_retain_t;
|
||||
|
||||
/**
|
||||
* \brief MQTT engine events
|
||||
*/
|
||||
typedef enum {
|
||||
MQTT_EVENT_CONNECTED,
|
||||
MQTT_EVENT_DISCONNECTED,
|
||||
|
||||
MQTT_EVENT_SUBACK,
|
||||
MQTT_EVENT_UNSUBACK,
|
||||
MQTT_EVENT_PUBLISH,
|
||||
MQTT_EVENT_PUBACK,
|
||||
|
||||
/* Errors */
|
||||
MQTT_EVENT_ERROR = 0x80,
|
||||
MQTT_EVENT_PROTOCOL_ERROR,
|
||||
MQTT_EVENT_CONNECTION_REFUSED_ERROR,
|
||||
MQTT_EVENT_DNS_ERROR,
|
||||
MQTT_EVENT_NOT_IMPLEMENTED_ERROR,
|
||||
/* Add more */
|
||||
} mqtt_event_t;
|
||||
|
||||
typedef enum {
|
||||
MQTT_STATUS_OK,
|
||||
|
||||
MQTT_STATUS_OUT_QUEUE_FULL,
|
||||
|
||||
/* Errors */
|
||||
MQTT_STATUS_ERROR = 0x80,
|
||||
MQTT_STATUS_NOT_CONNECTED_ERROR,
|
||||
MQTT_STATUS_INVALID_ARGS_ERROR,
|
||||
MQTT_STATUS_DNS_ERROR,
|
||||
} mqtt_status_t;
|
||||
|
||||
typedef enum {
|
||||
MQTT_QOS_LEVEL_0,
|
||||
MQTT_QOS_LEVEL_1,
|
||||
MQTT_QOS_LEVEL_2,
|
||||
} mqtt_qos_level_t;
|
||||
|
||||
typedef enum {
|
||||
MQTT_QOS_STATE_NO_ACK,
|
||||
MQTT_QOS_STATE_GOT_ACK,
|
||||
|
||||
/* Expand for QoS 2 */
|
||||
} mqtt_qos_state_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* This is the state of the connection itself.
|
||||
*
|
||||
* N.B. The order is important because of runtime checks on how far the
|
||||
* connection has proceeded.
|
||||
*/
|
||||
typedef enum {
|
||||
MQTT_CONN_STATE_ERROR,
|
||||
MQTT_CONN_STATE_DNS_ERROR,
|
||||
MQTT_CONN_STATE_DISCONNECTING,
|
||||
|
||||
MQTT_CONN_STATE_NOT_CONNECTED,
|
||||
MQTT_CONN_STATE_DNS_LOOKUP,
|
||||
MQTT_CONN_STATE_TCP_CONNECTING,
|
||||
MQTT_CONN_STATE_TCP_CONNECTED,
|
||||
MQTT_CONN_STATE_CONNECTING_TO_BROKER,
|
||||
MQTT_CONN_STATE_CONNECTED_TO_BROKER,
|
||||
MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT,
|
||||
MQTT_CONN_STATE_ABORT_IMMEDIATE,
|
||||
} mqtt_conn_state_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct mqtt_string {
|
||||
char *string;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that the pairing mid <-> QoS level only applies one-to-one if we only
|
||||
* allow the subscription of one topic at a time. Otherwise we will have an
|
||||
* ordered list of QoS levels corresponding to the order of topics.
|
||||
*
|
||||
* This could be part of a union of event data structures.
|
||||
*/
|
||||
struct mqtt_suback_event {
|
||||
uint16_t mid;
|
||||
mqtt_qos_level_t qos_level;
|
||||
};
|
||||
|
||||
/* This is the MQTT message that is exposed to the end user. */
|
||||
struct mqtt_message {
|
||||
uint32_t mid;
|
||||
char topic[MQTT_MAX_TOPIC_LENGTH + 1]; /* +1 for string termination */
|
||||
|
||||
uint8_t *payload_chunk;
|
||||
uint16_t payload_chunk_length;
|
||||
|
||||
uint8_t first_chunk;
|
||||
uint16_t payload_length;
|
||||
uint16_t payload_left;
|
||||
};
|
||||
|
||||
/* This struct represents a packet received from the MQTT server. */
|
||||
struct mqtt_in_packet {
|
||||
/* Used by the list interface, must be first in the struct. */
|
||||
struct mqtt_connection *next;
|
||||
|
||||
/* Total bytes read so far. Compared to the remaining length to to decide when
|
||||
* we've read the payload. */
|
||||
uint32_t byte_counter;
|
||||
uint8_t packet_received;
|
||||
|
||||
uint8_t fhdr;
|
||||
uint16_t remaining_length;
|
||||
uint16_t mid;
|
||||
|
||||
/* Helper variables needed to decode the remaining_length */
|
||||
uint8_t remaining_multiplier;
|
||||
uint8_t has_remaining_length;
|
||||
uint8_t remaining_length_bytes;
|
||||
|
||||
/* Not the same as payload in the MQTT sense, it also contains the variable
|
||||
* header.
|
||||
*/
|
||||
uint8_t payload_pos;
|
||||
uint8_t payload[MQTT_INPUT_BUFF_SIZE];
|
||||
|
||||
/* Message specific data */
|
||||
uint16_t topic_len;
|
||||
uint16_t topic_pos;
|
||||
uint8_t topic_len_received;
|
||||
uint8_t topic_received;
|
||||
};
|
||||
|
||||
/* This struct represents a packet sent to the MQTT server. */
|
||||
struct mqtt_out_packet {
|
||||
uint8_t fhdr;
|
||||
uint32_t remaining_length;
|
||||
uint8_t remaining_length_enc[MQTT_MAX_REMAINING_LENGTH_BYTES];
|
||||
uint8_t remaining_length_enc_bytes;
|
||||
uint16_t mid;
|
||||
char *topic;
|
||||
uint16_t topic_length;
|
||||
uint8_t *payload;
|
||||
uint32_t payload_size;
|
||||
mqtt_qos_level_t qos;
|
||||
mqtt_qos_state_t qos_state;
|
||||
mqtt_retain_t retain;
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief MQTT event callback function
|
||||
* \param m A pointer to a MQTT connection
|
||||
* \param event The event number
|
||||
* \param data A user-defined pointer
|
||||
*
|
||||
* The MQTT socket event callback function gets called whenever there is an
|
||||
* event on a MQTT connection, such as the connection getting connected
|
||||
* or closed.
|
||||
*/
|
||||
typedef void (*mqtt_event_callback_t)(struct mqtt_connection *m,
|
||||
mqtt_event_t event,
|
||||
void *data);
|
||||
|
||||
typedef void (*mqtt_topic_callback_t)(struct mqtt_connection *m,
|
||||
struct mqtt_message *msg);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct mqtt_will {
|
||||
struct mqtt_string topic;
|
||||
struct mqtt_string message;
|
||||
mqtt_qos_level_t qos;
|
||||
};
|
||||
|
||||
struct mqtt_credentials {
|
||||
struct mqtt_string username;
|
||||
struct mqtt_string password;
|
||||
};
|
||||
|
||||
struct mqtt_connection {
|
||||
/* Used by the list interface, must be first in the struct */
|
||||
struct mqtt_connection *next;
|
||||
struct timer t;
|
||||
|
||||
struct mqtt_string client_id;
|
||||
|
||||
uint8_t connect_vhdr_flags;
|
||||
uint8_t auto_reconnect;
|
||||
|
||||
uint16_t keep_alive;
|
||||
struct ctimer keep_alive_timer;
|
||||
uint8_t waiting_for_pingresp;
|
||||
|
||||
struct mqtt_will will;
|
||||
struct mqtt_credentials credentials;
|
||||
|
||||
mqtt_conn_state_t state;
|
||||
mqtt_event_callback_t event_callback;
|
||||
|
||||
/* Internal data */
|
||||
uint16_t mid_counter;
|
||||
|
||||
/* Used for communication between MQTT API and APP */
|
||||
uint8_t out_queue_full;
|
||||
struct process *app_process;
|
||||
|
||||
/* Outgoing data related */
|
||||
uint8_t *out_buffer_ptr;
|
||||
uint8_t out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE];
|
||||
uint8_t out_buffer_sent;
|
||||
struct mqtt_out_packet out_packet;
|
||||
struct pt out_proto_thread;
|
||||
uint32_t out_write_pos;
|
||||
uint16_t max_segment_size;
|
||||
|
||||
/* Incoming data related */
|
||||
uint8_t in_buffer[MQTT_TCP_INPUT_BUFF_SIZE];
|
||||
struct mqtt_in_packet in_packet;
|
||||
struct mqtt_message in_publish_msg;
|
||||
|
||||
/* TCP related information */
|
||||
char *server_host;
|
||||
uip_ipaddr_t server_ip;
|
||||
uint16_t server_port;
|
||||
struct tcp_socket socket;
|
||||
};
|
||||
/* This is the API exposed to the user. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initializes the MQTT engine.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param app_process A pointer to the application process handling the MQTT
|
||||
* connection.
|
||||
* \param client_id A pointer to the MQTT client ID.
|
||||
* \param event_callback Callback function responsible for handling the
|
||||
* callback from MQTT engine.
|
||||
* \param max_segment_size The TCP segment size to use for this MQTT/TCP
|
||||
* connection.
|
||||
* \return MQTT_STATUS_OK or MQTT_STATUS_INVALID_ARGS_ERROR
|
||||
*
|
||||
* This function initializes the MQTT engine and shall be called before any
|
||||
* other MQTT function.
|
||||
*/
|
||||
mqtt_status_t mqtt_register(struct mqtt_connection *conn,
|
||||
struct process *app_process,
|
||||
char *client_id,
|
||||
mqtt_event_callback_t event_callback,
|
||||
uint16_t max_segment_size);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Connects to a MQTT broker.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param host IP address of the broker to connect to.
|
||||
* \param port Port of the broker to connect to, default is MQTT port is 1883.
|
||||
* \param keep_alive Keep alive timer in seconds. Used by broker to handle
|
||||
* client disc. Defines the maximum time interval between two messages
|
||||
* from the client. Shall be min 1.5 x report interval.
|
||||
* \return MQTT_STATUS_OK or an error status
|
||||
*
|
||||
* This function connects to a MQTT broker.
|
||||
*/
|
||||
mqtt_status_t mqtt_connect(struct mqtt_connection *conn,
|
||||
char *host,
|
||||
uint16_t port,
|
||||
uint16_t keep_alive);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Disconnects from a MQTT broker.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
*
|
||||
* This function disconnects from a MQTT broker.
|
||||
*/
|
||||
void mqtt_disconnect(struct mqtt_connection *conn);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Subscribes to a MQTT topic.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param mid A pointer to message ID.
|
||||
* \param topic A pointer to the topic to subscribe to.
|
||||
* \param qos_level Quality Of Service level to use. Currently supports 0, 1.
|
||||
* \return MQTT_STATUS_OK or some error status
|
||||
*
|
||||
* This function subscribes to a topic on a MQTT broker.
|
||||
*/
|
||||
mqtt_status_t mqtt_subscribe(struct mqtt_connection *conn,
|
||||
uint16_t *mid,
|
||||
char *topic,
|
||||
mqtt_qos_level_t qos_level);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Unsubscribes from a MQTT topic.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param mid A pointer to message ID.
|
||||
* \param topic A pointer to the topic to unsubscribe from.
|
||||
* \return MQTT_STATUS_OK or some error status
|
||||
*
|
||||
* This function unsubscribes from a topic on a MQTT broker.
|
||||
*/
|
||||
mqtt_status_t mqtt_unsubscribe(struct mqtt_connection *conn,
|
||||
uint16_t *mid,
|
||||
char *topic);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Publish to a MQTT topic.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param mid A pointer to message ID.
|
||||
* \param topic A pointer to the topic to subscribe to.
|
||||
* \param payload A pointer to the topic payload.
|
||||
* \param payload_size Payload size.
|
||||
* \param qos_level Quality Of Service level to use. Currently supports 0, 1.
|
||||
* \param retain If the RETAIN flag is set to 1, in a PUBLISH Packet sent by a
|
||||
* Client to a Server, the Server MUST store the Application Message
|
||||
* and its QoS, so that it can be delivered to future subscribers whose
|
||||
* subscriptions match its topic name
|
||||
* \return MQTT_STATUS_OK or some error status
|
||||
*
|
||||
* This function publishes to a topic on a MQTT broker.
|
||||
*/
|
||||
mqtt_status_t mqtt_publish(struct mqtt_connection *conn,
|
||||
uint16_t *mid,
|
||||
char *topic,
|
||||
uint8_t *payload,
|
||||
uint32_t payload_size,
|
||||
mqtt_qos_level_t qos_level,
|
||||
mqtt_retain_t retain);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set the user name and password for a MQTT client.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param username A pointer to the user name.
|
||||
* \param password A pointer to the password.
|
||||
*
|
||||
* This function sets clients user name and password to use when connecting to
|
||||
* a MQTT broker.
|
||||
*/
|
||||
void mqtt_set_username_password(struct mqtt_connection *conn,
|
||||
char *username,
|
||||
char *password);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set the last will topic and message for a MQTT client.
|
||||
* \param conn A pointer to the MQTT connection.
|
||||
* \param topic A pointer to the Last Will topic.
|
||||
* \param message A pointer to the Last Will message (payload).
|
||||
* \param qos The desired QoS level.
|
||||
*
|
||||
* This function sets clients Last Will topic and message (payload).
|
||||
* If the Will Flag is set to 1 (using the function) this indicates that,
|
||||
* if the Connect request is accepted, a Will Message MUST be stored on the
|
||||
* Server and associated with the Network Connection. The Will Message MUST
|
||||
* be published when the Network Connection is subsequently closed.
|
||||
*
|
||||
* This functionality can be used to get notified that a device has
|
||||
* disconnected from the broker.
|
||||
*
|
||||
*/
|
||||
void mqtt_set_last_will(struct mqtt_connection *conn,
|
||||
char *topic,
|
||||
char *message,
|
||||
mqtt_qos_level_t qos);
|
||||
|
||||
#define mqtt_connected(conn) \
|
||||
((conn)->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER ? 1 : 0)
|
||||
|
||||
#define mqtt_ready(conn) \
|
||||
(!(conn)->out_queue_full && mqtt_connected((conn)))
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* MQTT_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
|
@ -113,7 +113,7 @@ makestrings(void)
|
|||
makeaddr(&addr, gateway);
|
||||
|
||||
#if UIP_UDP
|
||||
addrptr = resolv_getserver();
|
||||
addrptr = uip_nameserver_get(0);
|
||||
if(addrptr != NULL) {
|
||||
makeaddr(addrptr, dnsserver);
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ apply_tcpipconfig(void)
|
|||
#if UIP_UDP
|
||||
nullterminate(dnsserver);
|
||||
if(uiplib_ipaddrconv(dnsserver, &addr)) {
|
||||
resolv_conf(&addr);
|
||||
uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME);
|
||||
}
|
||||
#endif /* UIP_UDP */
|
||||
}
|
||||
|
|
|
@ -31,9 +31,11 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file Shell command for downloading files from a remote node.
|
||||
* \file
|
||||
*
|
||||
* Shell command for downloading files from a remote node.
|
||||
* Example usage:
|
||||
* 'download <node addr> <filename> | write <local_filename'.
|
||||
* 'download \<node addr\> \<filename\> | write \<local_filename\>'.
|
||||
*
|
||||
* \author Luca Mottola <luca@sics.se>, Fredrik Osterlind <fros@sics.se>
|
||||
*/
|
||||
|
|
|
@ -35,12 +35,12 @@
|
|||
* Coffee: A file system for a variety of storage types in
|
||||
* memory-constrained devices.
|
||||
*
|
||||
* For further information, see "Enabling Large-Scale Storage in
|
||||
* Sensor Networks with the Coffee File System" in the proceedings
|
||||
* For further information, see "Enabling Large-Scale Storage in
|
||||
* Sensor Networks with the Coffee File System" in the proceedings
|
||||
* of ACM/IEEE IPSN 2009.
|
||||
*
|
||||
* \author
|
||||
* Nicolas Tsiftes <nvt@sics.se>
|
||||
* Nicolas Tsiftes <nvt@sics.se>
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
@ -62,23 +62,23 @@
|
|||
/* Micro logs enable modifications on storage types that do not support
|
||||
in-place updates. This applies primarily to flash memories. */
|
||||
#ifndef COFFEE_MICRO_LOGS
|
||||
#define COFFEE_MICRO_LOGS 1
|
||||
#define COFFEE_MICRO_LOGS 1
|
||||
#endif
|
||||
|
||||
/* If the files are expected to be appended to only, this parameter
|
||||
/* If the files are expected to be appended to only, this parameter
|
||||
can be set to save some code space. */
|
||||
#ifndef COFFEE_APPEND_ONLY
|
||||
#define COFFEE_APPEND_ONLY 0
|
||||
#define COFFEE_APPEND_ONLY 0
|
||||
#endif
|
||||
|
||||
#if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY
|
||||
#error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set."
|
||||
#endif
|
||||
|
||||
/* I/O semantics can be set on file descriptors in order to optimize
|
||||
/* I/O semantics can be set on file descriptors in order to optimize
|
||||
file access on certain storage types. */
|
||||
#ifndef COFFEE_IO_SEMANTICS
|
||||
#define COFFEE_IO_SEMANTICS 0
|
||||
#define COFFEE_IO_SEMANTICS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -87,72 +87,72 @@
|
|||
* to longer garbage collection procedures.
|
||||
*/
|
||||
#ifndef COFFEE_EXTENDED_WEAR_LEVELLING
|
||||
#define COFFEE_EXTENDED_WEAR_LEVELLING 1
|
||||
#define COFFEE_EXTENDED_WEAR_LEVELLING 1
|
||||
#endif
|
||||
|
||||
#if COFFEE_START & (COFFEE_SECTOR_SIZE - 1)
|
||||
#error COFFEE_START must point to the first byte in a sector.
|
||||
#endif
|
||||
|
||||
#define COFFEE_FD_FREE 0x0
|
||||
#define COFFEE_FD_READ 0x1
|
||||
#define COFFEE_FD_WRITE 0x2
|
||||
#define COFFEE_FD_APPEND 0x4
|
||||
#define COFFEE_FD_FREE 0x0
|
||||
#define COFFEE_FD_READ 0x1
|
||||
#define COFFEE_FD_WRITE 0x2
|
||||
#define COFFEE_FD_APPEND 0x4
|
||||
|
||||
#define COFFEE_FILE_MODIFIED 0x1
|
||||
#define COFFEE_FILE_MODIFIED 0x1
|
||||
|
||||
#define INVALID_PAGE ((coffee_page_t)-1)
|
||||
#define UNKNOWN_OFFSET ((cfs_offset_t)-1)
|
||||
#define INVALID_PAGE ((coffee_page_t)-1)
|
||||
#define UNKNOWN_OFFSET ((cfs_offset_t)-1)
|
||||
|
||||
#define REMOVE_LOG 1
|
||||
#define CLOSE_FDS 1
|
||||
#define ALLOW_GC 1
|
||||
#define REMOVE_LOG 1
|
||||
#define CLOSE_FDS 1
|
||||
#define ALLOW_GC 1
|
||||
|
||||
/* "Greedy" garbage collection erases as many sectors as possible. */
|
||||
#define GC_GREEDY 0
|
||||
#define GC_GREEDY 0
|
||||
/* "Reluctant" garbage collection stops after erasing one sector. */
|
||||
#define GC_RELUCTANT 1
|
||||
#define GC_RELUCTANT 1
|
||||
|
||||
/* File descriptor macros. */
|
||||
#define FD_VALID(fd) \
|
||||
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
|
||||
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
|
||||
#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ)
|
||||
#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE)
|
||||
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
|
||||
#define FD_VALID(fd) \
|
||||
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
|
||||
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
|
||||
#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ)
|
||||
#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE)
|
||||
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
|
||||
|
||||
/* File object macros. */
|
||||
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
|
||||
#define FILE_FREE(file) ((file)->max_pages == 0)
|
||||
#define FILE_UNREFERENCED(file) ((file)->references == 0)
|
||||
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
|
||||
#define FILE_FREE(file) ((file)->max_pages == 0)
|
||||
#define FILE_UNREFERENCED(file) ((file)->references == 0)
|
||||
|
||||
/* File header flags. */
|
||||
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
||||
#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */
|
||||
#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */
|
||||
#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */
|
||||
#define HDR_FLAG_LOG 0x10 /* Log file. */
|
||||
#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */
|
||||
#define HDR_FLAG_VALID 0x1 /* Completely written header. */
|
||||
#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */
|
||||
#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */
|
||||
#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */
|
||||
#define HDR_FLAG_LOG 0x10 /* Log file. */
|
||||
#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */
|
||||
|
||||
/* File header macros. */
|
||||
#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag))
|
||||
#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID)
|
||||
#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED)
|
||||
#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr)
|
||||
#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG)
|
||||
#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED)
|
||||
#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED)
|
||||
#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE)
|
||||
#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \
|
||||
!HDR_OBSOLETE(hdr) && \
|
||||
!HDR_ISOLATED(hdr))
|
||||
#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag))
|
||||
#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID)
|
||||
#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED)
|
||||
#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr)
|
||||
#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG)
|
||||
#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED)
|
||||
#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED)
|
||||
#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE)
|
||||
#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \
|
||||
!HDR_OBSOLETE(hdr) && \
|
||||
!HDR_ISOLATED(hdr))
|
||||
|
||||
/* Shortcuts derived from the hardware-dependent configuration of Coffee. */
|
||||
#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
|
||||
#define COFFEE_PAGE_COUNT \
|
||||
((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE))
|
||||
#define COFFEE_PAGES_PER_SECTOR \
|
||||
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
|
||||
#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
|
||||
#define COFFEE_PAGE_COUNT \
|
||||
((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE))
|
||||
#define COFFEE_PAGES_PER_SECTOR \
|
||||
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
|
||||
|
||||
/* This structure is used for garbage collection statistics. */
|
||||
struct sector_status {
|
||||
|
@ -181,7 +181,7 @@ struct file_desc {
|
|||
#endif
|
||||
};
|
||||
|
||||
/* The file header structure mimics the representation of file headers
|
||||
/* The file header structure mimics the representation of file headers
|
||||
in the physical storage medium. */
|
||||
struct file_header {
|
||||
coffee_page_t log_page;
|
||||
|
@ -201,9 +201,9 @@ struct log_param {
|
|||
};
|
||||
|
||||
/*
|
||||
* The protected memory consists of structures that should not be
|
||||
* overwritten during system checkpointing because they may be used by
|
||||
* the checkpointing implementation. These structures need not be
|
||||
* The protected memory consists of structures that should not be
|
||||
* overwritten during system checkpointing because they may be used by
|
||||
* the checkpointing implementation. These structures need not be
|
||||
* protected if checkpointing is not used.
|
||||
*/
|
||||
static struct protected_mem_t {
|
||||
|
@ -212,10 +212,10 @@ static struct protected_mem_t {
|
|||
coffee_page_t next_free;
|
||||
char gc_wait;
|
||||
} protected_mem;
|
||||
static struct file * const coffee_files = protected_mem.coffee_files;
|
||||
static struct file_desc * const coffee_fd_set = protected_mem.coffee_fd_set;
|
||||
static coffee_page_t * const next_free = &protected_mem.next_free;
|
||||
static char * const gc_wait = &protected_mem.gc_wait;
|
||||
static struct file *const coffee_files = protected_mem.coffee_files;
|
||||
static struct file_desc *const coffee_fd_set = protected_mem.coffee_fd_set;
|
||||
static coffee_page_t *const next_free = &protected_mem.next_free;
|
||||
static char *const gc_wait = &protected_mem.gc_wait;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -256,8 +256,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
|||
active = obsolete = free = 0;
|
||||
|
||||
/*
|
||||
* get_sector_status() is an iterative function using local static
|
||||
* state. It therefore requires that the caller starts iterating from
|
||||
* get_sector_status() is an iterative function using local static
|
||||
* state. It therefore requires that the caller starts iterating from
|
||||
* sector 0 in order to reset the internal state.
|
||||
*/
|
||||
if(sector == 0) {
|
||||
|
@ -269,8 +269,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
|||
sector_end = sector_start + COFFEE_PAGES_PER_SECTOR;
|
||||
|
||||
/*
|
||||
* Account for pages belonging to a file starting in a previous
|
||||
* segment that extends into this segment. If the whole segment is
|
||||
* Account for pages belonging to a file starting in a previous
|
||||
* segment that extends into this segment. If the whole segment is
|
||||
* covered, we do not need to continue counting pages in this iteration.
|
||||
*/
|
||||
if(last_pages_are_active) {
|
||||
|
@ -289,7 +289,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
|||
obsolete = skip_pages;
|
||||
}
|
||||
|
||||
/* Determine the amount of pages of each type that have not been
|
||||
/* Determine the amount of pages of each type that have not been
|
||||
accounted for yet in the current sector. */
|
||||
for(page = sector_start + skip_pages; page < sector_end;) {
|
||||
read_header(&hdr, page);
|
||||
|
@ -312,10 +312,10 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
|||
|
||||
/*
|
||||
* Determine the amount of pages in the following sectors that
|
||||
* should be remembered for the next iteration. This is necessary
|
||||
* because no page except the first of a file contains information
|
||||
* should be remembered for the next iteration. This is necessary
|
||||
* because no page except the first of a file contains information
|
||||
* about what type of page it is. A side effect of remembering this
|
||||
* amount is that there is no need to read in the headers of each
|
||||
* amount is that there is no need to read in the headers of each
|
||||
* of these pages from the storage.
|
||||
*/
|
||||
skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR;
|
||||
|
@ -332,14 +332,14 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
|
|||
stats->free = free;
|
||||
|
||||
/*
|
||||
* To avoid unnecessary page isolation, we notify the caller that
|
||||
* "skip_pages" pages should be isolated only if the current file extent
|
||||
* ends in the next sector. If the file extent ends in a more distant
|
||||
* sector, however, the garbage collection can free the next sector
|
||||
* immediately without requiring page isolation.
|
||||
* To avoid unnecessary page isolation, we notify the caller that
|
||||
* "skip_pages" pages should be isolated only if the current file extent
|
||||
* ends in the next sector. If the file extent ends in a more distant
|
||||
* sector, however, the garbage collection can free the next sector
|
||||
* immediately without requiring page isolation.
|
||||
*/
|
||||
return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ?
|
||||
0 : skip_pages;
|
||||
0 : skip_pages;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -359,7 +359,6 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages)
|
|||
}
|
||||
PRINTF("Coffee: Isolated %u pages starting in sector %d\n",
|
||||
(unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR);
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -370,7 +369,7 @@ collect_garbage(int mode)
|
|||
coffee_page_t first_page, isolation_count;
|
||||
|
||||
PRINTF("Coffee: Running the file system garbage collector in %s mode\n",
|
||||
mode == GC_RELUCTANT ? "reluctant" : "greedy");
|
||||
mode == GC_RELUCTANT ? "reluctant" : "greedy");
|
||||
/*
|
||||
* The garbage collector erases as many sectors as possible. A sector is
|
||||
* erasable if there are only free or obsolete pages in it.
|
||||
|
@ -378,8 +377,8 @@ collect_garbage(int mode)
|
|||
for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
|
||||
isolation_count = get_sector_status(sector, &stats);
|
||||
PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
|
||||
sector, (unsigned)stats.active,
|
||||
(unsigned)stats.obsolete, (unsigned)stats.free);
|
||||
sector, (unsigned)stats.active,
|
||||
(unsigned)stats.obsolete, (unsigned)stats.free);
|
||||
|
||||
if(stats.active > 0) {
|
||||
continue;
|
||||
|
@ -410,13 +409,13 @@ static coffee_page_t
|
|||
next_file(coffee_page_t page, struct file_header *hdr)
|
||||
{
|
||||
/*
|
||||
* The quick-skip algorithm for finding file extents is the most
|
||||
* essential part of Coffee. The file allocation rules enables this
|
||||
* algorithm to quickly jump over free areas and allocated extents
|
||||
* The quick-skip algorithm for finding file extents is the most
|
||||
* essential part of Coffee. The file allocation rules enables this
|
||||
* algorithm to quickly jump over free areas and allocated extents
|
||||
* after reading single headers and determining their status.
|
||||
*
|
||||
* The worst-case performance occurs when we encounter multiple long
|
||||
* sequences of isolated pages, but such sequences are uncommon and
|
||||
* The worst-case performance occurs when we encounter multiple long
|
||||
* sequences of isolated pages, but such sequences are uncommon and
|
||||
* always shorter than a sector.
|
||||
*/
|
||||
if(HDR_FREE(*hdr)) {
|
||||
|
@ -424,7 +423,7 @@ next_file(coffee_page_t page, struct file_header *hdr)
|
|||
} else if(HDR_ISOLATED(*hdr)) {
|
||||
return page + 1;
|
||||
}
|
||||
return page + hdr->max_pages;
|
||||
return page + hdr->max_pages;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct file *
|
||||
|
@ -475,7 +474,7 @@ find_file(const char *name)
|
|||
int i;
|
||||
struct file_header hdr;
|
||||
coffee_page_t page;
|
||||
|
||||
|
||||
/* First check if the file metadata is cached. */
|
||||
for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) {
|
||||
if(FILE_FREE(&coffee_files[i])) {
|
||||
|
@ -487,7 +486,7 @@ find_file(const char *name)
|
|||
return &coffee_files[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Scan the flash memory sequentially otherwise. */
|
||||
for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) {
|
||||
read_header(&hdr, page);
|
||||
|
@ -521,10 +520,10 @@ file_end(coffee_page_t start)
|
|||
COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE);
|
||||
for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) {
|
||||
if(buf[i] != 0) {
|
||||
if(page == 0 && i < sizeof(hdr)) {
|
||||
return 0;
|
||||
}
|
||||
return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr);
|
||||
if(page == 0 && i < sizeof(hdr)) {
|
||||
return 0;
|
||||
}
|
||||
return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +543,7 @@ find_contiguous_pages(coffee_page_t amount)
|
|||
read_header(&hdr, page);
|
||||
if(HDR_FREE(hdr)) {
|
||||
if(start == INVALID_PAGE) {
|
||||
start = page;
|
||||
start = page;
|
||||
if(start + amount >= COFFEE_PAGE_COUNT) {
|
||||
/* We can stop immediately if the remaining pages are not enough. */
|
||||
break;
|
||||
|
@ -557,9 +556,9 @@ find_contiguous_pages(coffee_page_t amount)
|
|||
|
||||
if(start + amount <= page) {
|
||||
if(start == *next_free) {
|
||||
*next_free = start + amount;
|
||||
}
|
||||
return start;
|
||||
*next_free = start + amount;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
} else {
|
||||
start = INVALID_PAGE;
|
||||
|
@ -596,7 +595,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds,
|
|||
if(close_fds) {
|
||||
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
|
||||
if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) {
|
||||
coffee_fd_set[i].flags = COFFEE_FD_FREE;
|
||||
coffee_fd_set[i].flags = COFFEE_FD_FREE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -622,12 +621,12 @@ static coffee_page_t
|
|||
page_count(cfs_offset_t size)
|
||||
{
|
||||
return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) /
|
||||
COFFEE_PAGE_SIZE;
|
||||
COFFEE_PAGE_SIZE;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static struct file *
|
||||
reserve(const char *name, coffee_page_t pages,
|
||||
int allow_duplicates, unsigned flags)
|
||||
int allow_duplicates, unsigned flags)
|
||||
{
|
||||
struct file_header hdr;
|
||||
coffee_page_t page;
|
||||
|
@ -657,7 +656,7 @@ reserve(const char *name, coffee_page_t pages,
|
|||
write_header(&hdr, page);
|
||||
|
||||
PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n",
|
||||
pages, page, name);
|
||||
pages, page, name);
|
||||
|
||||
file = load_file(page, &hdr);
|
||||
if(file != NULL) {
|
||||
|
@ -670,19 +669,19 @@ reserve(const char *name, coffee_page_t pages,
|
|||
#if COFFEE_MICRO_LOGS
|
||||
static void
|
||||
adjust_log_config(struct file_header *hdr,
|
||||
uint16_t *log_record_size, uint16_t *log_records)
|
||||
uint16_t *log_record_size, uint16_t *log_records)
|
||||
{
|
||||
*log_record_size = hdr->log_record_size == 0 ?
|
||||
COFFEE_PAGE_SIZE : hdr->log_record_size;
|
||||
COFFEE_PAGE_SIZE : hdr->log_record_size;
|
||||
*log_records = hdr->log_records == 0 ?
|
||||
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
|
||||
COFFEE_LOG_SIZE / *log_record_size : hdr->log_records;
|
||||
}
|
||||
#endif /* COFFEE_MICRO_LOGS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if COFFEE_MICRO_LOGS
|
||||
static uint16_t
|
||||
modify_log_buffer(uint16_t log_record_size,
|
||||
cfs_offset_t *offset, uint16_t *size)
|
||||
cfs_offset_t *offset, uint16_t *size)
|
||||
{
|
||||
uint16_t region;
|
||||
|
||||
|
@ -700,7 +699,7 @@ modify_log_buffer(uint16_t log_record_size,
|
|||
#if COFFEE_MICRO_LOGS
|
||||
static int
|
||||
get_record_index(coffee_page_t log_page, uint16_t search_records,
|
||||
uint16_t region)
|
||||
uint16_t region)
|
||||
{
|
||||
cfs_offset_t base;
|
||||
uint16_t processed;
|
||||
|
@ -709,30 +708,30 @@ get_record_index(coffee_page_t log_page, uint16_t search_records,
|
|||
|
||||
base = absolute_offset(log_page, sizeof(uint16_t) * search_records);
|
||||
batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ?
|
||||
COFFEE_LOG_TABLE_LIMIT : search_records;
|
||||
COFFEE_LOG_TABLE_LIMIT : search_records;
|
||||
processed = 0;
|
||||
match_index = -1;
|
||||
|
||||
{
|
||||
uint16_t indices[batch_size];
|
||||
uint16_t indices[batch_size];
|
||||
|
||||
while(processed < search_records && match_index < 0) {
|
||||
if(batch_size + processed > search_records) {
|
||||
batch_size = search_records - processed;
|
||||
}
|
||||
|
||||
base -= batch_size * sizeof(indices[0]);
|
||||
COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base);
|
||||
|
||||
for(i = batch_size - 1; i >= 0; i--) {
|
||||
if(indices[i] - 1 == region) {
|
||||
match_index = search_records - processed - (batch_size - i);
|
||||
break;
|
||||
while(processed < search_records && match_index < 0) {
|
||||
if(batch_size + processed > search_records) {
|
||||
batch_size = search_records - processed;
|
||||
}
|
||||
}
|
||||
|
||||
processed += batch_size;
|
||||
}
|
||||
base -= batch_size * sizeof(indices[0]);
|
||||
COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base);
|
||||
|
||||
for(i = batch_size - 1; i >= 0; i--) {
|
||||
if(indices[i] - 1 == region) {
|
||||
match_index = search_records - processed - (batch_size - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
processed += batch_size;
|
||||
}
|
||||
}
|
||||
|
||||
return match_index;
|
||||
|
@ -839,7 +838,7 @@ merge_log(coffee_page_t file_page, int extend)
|
|||
} while(n != 0);
|
||||
|
||||
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
|
||||
if(coffee_fd_set[i].flags != COFFEE_FD_FREE &&
|
||||
if(coffee_fd_set[i].flags != COFFEE_FD_FREE &&
|
||||
coffee_fd_set[i].file->page == file_page) {
|
||||
coffee_fd_set[i].file = new_file;
|
||||
new_file->references++;
|
||||
|
@ -869,7 +868,7 @@ merge_log(coffee_page_t file_page, int extend)
|
|||
#if COFFEE_MICRO_LOGS
|
||||
static int
|
||||
find_next_record(struct file *file, coffee_page_t log_page,
|
||||
int log_records)
|
||||
int log_records)
|
||||
{
|
||||
int log_record, preferred_batch_size;
|
||||
|
||||
|
@ -878,7 +877,7 @@ find_next_record(struct file *file, coffee_page_t log_page,
|
|||
}
|
||||
|
||||
preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ?
|
||||
COFFEE_LOG_TABLE_LIMIT : log_records;
|
||||
COFFEE_LOG_TABLE_LIMIT : log_records;
|
||||
{
|
||||
/* The next log record is unknown at this point; search for it. */
|
||||
uint16_t indices[preferred_batch_size];
|
||||
|
@ -888,15 +887,15 @@ find_next_record(struct file *file, coffee_page_t log_page,
|
|||
log_record = log_records;
|
||||
for(processed = 0; processed < log_records; processed += batch_size) {
|
||||
batch_size = log_records - processed >= preferred_batch_size ?
|
||||
preferred_batch_size : log_records - processed;
|
||||
preferred_batch_size : log_records - processed;
|
||||
|
||||
COFFEE_READ(&indices, batch_size * sizeof(indices[0]),
|
||||
absolute_offset(log_page, processed * sizeof(indices[0])));
|
||||
absolute_offset(log_page, processed * sizeof(indices[0])));
|
||||
for(log_record = 0; log_record < batch_size; log_record++) {
|
||||
if(indices[log_record] == 0) {
|
||||
log_record += processed;
|
||||
break;
|
||||
}
|
||||
if(indices[log_record] == 0) {
|
||||
log_record += processed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -940,7 +939,7 @@ write_log_page(struct file *file, struct log_param *lp)
|
|||
return -1;
|
||||
}
|
||||
PRINTF("Coffee: Created a log structure for file %s at page %u\n",
|
||||
hdr.name, (unsigned)log_page);
|
||||
hdr.name, (unsigned)log_page);
|
||||
hdr.log_page = log_page;
|
||||
log_record = 0;
|
||||
}
|
||||
|
@ -953,9 +952,9 @@ write_log_page(struct file *file, struct log_param *lp)
|
|||
lp_out.size = log_record_size;
|
||||
|
||||
if((lp->offset > 0 || lp->size != log_record_size) &&
|
||||
read_log_page(&hdr, log_record, &lp_out) < 0) {
|
||||
read_log_page(&hdr, log_record, &lp_out) < 0) {
|
||||
COFFEE_READ(copy_buf, sizeof(copy_buf),
|
||||
absolute_offset(file->page, offset));
|
||||
absolute_offset(file->page, offset));
|
||||
}
|
||||
|
||||
memcpy(©_buf[lp->offset], lp->buf, lp->size);
|
||||
|
@ -967,11 +966,11 @@ write_log_page(struct file *file, struct log_param *lp)
|
|||
offset = absolute_offset(log_page, 0);
|
||||
++region;
|
||||
COFFEE_WRITE(®ion, sizeof(region),
|
||||
offset + log_record * sizeof(region));
|
||||
offset + log_record * sizeof(region));
|
||||
|
||||
offset += log_records * sizeof(region);
|
||||
COFFEE_WRITE(copy_buf, sizeof(copy_buf),
|
||||
offset + log_record * log_record_size);
|
||||
offset + log_record * log_record_size);
|
||||
file->record_count = log_record + 1;
|
||||
}
|
||||
|
||||
|
@ -1171,7 +1170,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
|||
if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) {
|
||||
#endif
|
||||
while(size + fdp->offset + sizeof(struct file_header) >
|
||||
(file->max_pages * COFFEE_PAGE_SIZE)) {
|
||||
(file->max_pages * COFFEE_PAGE_SIZE)) {
|
||||
if(merge_log(file->page, 1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1179,7 +1178,7 @@ cfs_write(int fd, const void *buf, unsigned size)
|
|||
PRINTF("Extended the file at page %u\n", (unsigned)file->page);
|
||||
}
|
||||
#if COFFEE_IO_SEMANTICS
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if COFFEE_MICRO_LOGS
|
||||
|
@ -1196,19 +1195,19 @@ cfs_write(int fd, const void *buf, unsigned size)
|
|||
lp.size = bytes_left;
|
||||
i = write_log_page(file, &lp);
|
||||
if(i < 0) {
|
||||
/* Return -1 if we wrote nothing because the log write failed. */
|
||||
if(size == bytes_left) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* Return -1 if we wrote nothing because the log write failed. */
|
||||
if(size == bytes_left) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
} else if(i == 0) {
|
||||
/* The file was merged with the log. */
|
||||
file = fdp->file;
|
||||
file = fdp->file;
|
||||
} else {
|
||||
/* A log record was written. */
|
||||
bytes_left -= i;
|
||||
fdp->offset += i;
|
||||
buf = (char *)buf + i;
|
||||
/* A log record was written. */
|
||||
bytes_left -= i;
|
||||
fdp->offset += i;
|
||||
buf = (char *)buf + i;
|
||||
|
||||
/* Update the file end for a potential log merge that might
|
||||
occur while writing log records. */
|
||||
|
@ -1231,15 +1230,15 @@ cfs_write(int fd, const void *buf, unsigned size)
|
|||
} else {
|
||||
#endif /* COFFEE_MICRO_LOGS */
|
||||
#if COFFEE_APPEND_ONLY
|
||||
if(fdp->offset < file->end) {
|
||||
return -1;
|
||||
}
|
||||
if(fdp->offset < file->end) {
|
||||
return -1;
|
||||
}
|
||||
#endif /* COFFEE_APPEND_ONLY */
|
||||
|
||||
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
|
||||
fdp->offset += size;
|
||||
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
|
||||
fdp->offset += size;
|
||||
#if COFFEE_MICRO_LOGS
|
||||
}
|
||||
}
|
||||
#endif /* COFFEE_MICRO_LOGS */
|
||||
|
||||
if(fdp->offset > file->end) {
|
||||
|
@ -1253,7 +1252,7 @@ int
|
|||
cfs_opendir(struct cfs_dir *dir, const char *name)
|
||||
{
|
||||
/*
|
||||
* Coffee is only guaranteed to support "/" and ".", but it does not
|
||||
* Coffee is only guaranteed to support "/" and ".", but it does not
|
||||
* currently enforce this.
|
||||
*/
|
||||
memset(dir->dummy_space, 0, sizeof(coffee_page_t));
|
||||
|
@ -1300,7 +1299,7 @@ cfs_coffee_reserve(const char *name, cfs_offset_t size)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
cfs_coffee_configure_log(const char *filename, unsigned log_size,
|
||||
unsigned log_record_size)
|
||||
unsigned log_record_size)
|
||||
{
|
||||
struct file *file;
|
||||
struct file_header hdr;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "net/ip/uiplib.h"
|
||||
#include "net/ip/uip-udp-packet.h"
|
||||
#include "net/ip/simple-udp.h"
|
||||
#include "net/ip/uip-nameserver.h"
|
||||
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
#include "net/ipv6/uip-icmp6.h"
|
||||
|
|
|
@ -201,6 +201,7 @@ void ctk_draw_clear_window(struct ctk_window *window,
|
|||
* drawn, in screen coordinates (line 1 is the first line below the
|
||||
* menus)
|
||||
*
|
||||
* \param draw_borders The border style
|
||||
*/
|
||||
void ctk_draw_window(struct ctk_window *window,
|
||||
unsigned char focus,
|
||||
|
@ -318,7 +319,7 @@ extern unsigned char ctk_draw_windowborder_width,
|
|||
/**
|
||||
* The character used for the Return/Enter key.
|
||||
*
|
||||
* \define #define CH_ENTER '\n'
|
||||
* \#define CH_ENTER '\n'
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -77,7 +77,7 @@ unsigned short crc16_add(unsigned char b, unsigned short crc);
|
|||
* \brief Calculate the CRC16 over a data area
|
||||
* \param data Pointer to the data
|
||||
* \param datalen The length of the data
|
||||
* \param crc The accumulated CRC that is to be updated (or zero).
|
||||
* \param acc The accumulated CRC that is to be updated (or zero).
|
||||
* \return The CRC16 checksum.
|
||||
*
|
||||
* This function calculates the CRC16 checksum of a data area.
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "net/ip/tcpip.h"
|
||||
#include "net/ip/resolv.h"
|
||||
#include "net/ip/uip-udp-packet.h"
|
||||
#include "net/ip/uip-nameserver.h"
|
||||
#include "lib/random.h"
|
||||
|
||||
#ifndef DEBUG
|
||||
|
@ -227,17 +228,6 @@ struct dns_hdr {
|
|||
uint16_t numextrarr;
|
||||
};
|
||||
|
||||
/** These default values for the DNS server are Google's public DNS:
|
||||
* <https://developers.google.com/speed/public-dns/docs/using>
|
||||
*/
|
||||
static uip_ipaddr_t resolv_default_dns_server =
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
{ { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 } };
|
||||
#else /* NETSTACK_CONF_WITH_IPV6 */
|
||||
{ { 8, 8, 8, 8 } };
|
||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
||||
|
||||
/** \internal The DNS answer message structure. */
|
||||
struct dns_answer {
|
||||
/* DNS answer record starts with either a domain name or a pointer
|
||||
|
@ -269,6 +259,7 @@ struct namemap {
|
|||
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
|
||||
uip_ipaddr_t ipaddr;
|
||||
uint8_t err;
|
||||
uint8_t server;
|
||||
#if RESOLV_CONF_SUPPORTS_MDNS
|
||||
int is_mdns:1, is_probe:1;
|
||||
#endif
|
||||
|
@ -637,6 +628,21 @@ mdns_prep_host_announce_packet(void)
|
|||
}
|
||||
#endif /* RESOLV_CONF_SUPPORTS_MDNS */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char
|
||||
try_next_server(struct namemap *namemapptr)
|
||||
{
|
||||
#if VERBOSE_DEBUG
|
||||
printf("server %d\n", namemapptr->server);
|
||||
#endif
|
||||
namemapptr->server++;
|
||||
if(uip_nameserver_get(namemapptr->server) != NULL) {
|
||||
namemapptr->retries = 0;
|
||||
return 1;
|
||||
}
|
||||
namemapptr->server = 0;
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \internal
|
||||
* Runs through the list of names to see if there are any that have
|
||||
* not yet been queried and, if so, sends out a query.
|
||||
|
@ -666,16 +672,20 @@ check_entries(void)
|
|||
if(++namemapptr->retries == RESOLV_CONF_MAX_RETRIES)
|
||||
#endif /* RESOLV_CONF_SUPPORTS_MDNS */
|
||||
{
|
||||
/* STATE_ERROR basically means "not found". */
|
||||
namemapptr->state = STATE_ERROR;
|
||||
/* Try the next server (if possible) before failing. Otherwise
|
||||
simply mark the entry as failed. */
|
||||
if(try_next_server(namemapptr) == 0) {
|
||||
/* STATE_ERROR basically means "not found". */
|
||||
namemapptr->state = STATE_ERROR;
|
||||
|
||||
#if RESOLV_SUPPORTS_RECORD_EXPIRATION
|
||||
/* Keep the "not found" error valid for 30 seconds */
|
||||
namemapptr->expiration = clock_seconds() + 30;
|
||||
/* Keep the "not found" error valid for 30 seconds */
|
||||
namemapptr->expiration = clock_seconds() + 30;
|
||||
#endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */
|
||||
|
||||
resolv_found(namemapptr->name, NULL);
|
||||
continue;
|
||||
resolv_found(namemapptr->name, NULL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3;
|
||||
|
||||
|
@ -747,7 +757,9 @@ check_entries(void)
|
|||
} else {
|
||||
uip_udp_packet_sendto(resolv_conn, uip_appdata,
|
||||
(query - (uint8_t *) uip_appdata),
|
||||
&resolv_default_dns_server, UIP_HTONS(DNS_PORT));
|
||||
(const uip_ipaddr_t *)
|
||||
uip_nameserver_get(namemapptr->server),
|
||||
UIP_HTONS(DNS_PORT));
|
||||
|
||||
PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i,
|
||||
namemapptr->name);
|
||||
|
@ -755,7 +767,8 @@ check_entries(void)
|
|||
#else /* RESOLV_CONF_SUPPORTS_MDNS */
|
||||
uip_udp_packet_sendto(resolv_conn, uip_appdata,
|
||||
(query - (uint8_t *) uip_appdata),
|
||||
&resolv_default_dns_server, UIP_HTONS(DNS_PORT));
|
||||
uip_nameserver_get(namemapptr->server),
|
||||
UIP_HTONS(DNS_PORT));
|
||||
PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i,
|
||||
namemapptr->name);
|
||||
#endif /* RESOLV_CONF_SUPPORTS_MDNS */
|
||||
|
@ -1041,11 +1054,28 @@ newdata(void)
|
|||
uip_ipaddr_copy(&namemapptr->ipaddr, (uip_ipaddr_t *) ans->ipaddr);
|
||||
|
||||
resolv_found(namemapptr->name, &namemapptr->ipaddr);
|
||||
break;
|
||||
|
||||
skip_to_next_answer:
|
||||
queryptr = (unsigned char *)skip_name(queryptr) + 10 + uip_htons(ans->len);
|
||||
--nanswers;
|
||||
}
|
||||
|
||||
/* Got to this point there's no answer, try next nameserver if available
|
||||
since this one doesn't know the answer */
|
||||
#if RESOLV_CONF_SUPPORTS_MDNS
|
||||
if(nanswers == 0 && UIP_UDP_BUF->srcport != UIP_HTONS(MDNS_PORT)
|
||||
&& hdr->id != 0)
|
||||
#else
|
||||
if(nanswers == 0)
|
||||
#endif
|
||||
{
|
||||
if(try_next_server(namemapptr)) {
|
||||
namemapptr->state = STATE_ASKING;
|
||||
process_post(&resolv_process, PROCESS_EVENT_TIMER, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if RESOLV_CONF_SUPPORTS_MDNS
|
||||
|
@ -1405,31 +1435,6 @@ resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr)
|
|||
return ret;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Obtain the currently configured DNS server.
|
||||
*
|
||||
* \return A pointer to a 4-byte representation of the IP address of
|
||||
* the currently configured DNS server or NULL if no DNS server has
|
||||
* been configured.
|
||||
*/
|
||||
uip_ipaddr_t *
|
||||
resolv_getserver(void)
|
||||
{
|
||||
return &resolv_default_dns_server;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Configure a DNS server.
|
||||
*
|
||||
* \param dnsserver A pointer to a 4-byte representation of the IP
|
||||
* address of the DNS server to be configured.
|
||||
*/
|
||||
void
|
||||
resolv_conf(const uip_ipaddr_t * dnsserver)
|
||||
{
|
||||
uip_ipaddr_copy(&resolv_default_dns_server, dnsserver);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \internal
|
||||
* Callback function which is called when a hostname is found.
|
||||
*
|
||||
|
|
|
@ -57,11 +57,6 @@
|
|||
*/
|
||||
CCIF extern process_event_t resolv_event_found;
|
||||
|
||||
/* Functions. */
|
||||
CCIF void resolv_conf(const uip_ipaddr_t * dnsserver);
|
||||
|
||||
CCIF uip_ipaddr_t *resolv_getserver(void);
|
||||
|
||||
enum {
|
||||
/** Hostname is fresh and usable. This response is cached and will eventually
|
||||
* expire to RESOLV_STATUS_EXPIRED.*/
|
||||
|
@ -95,6 +90,7 @@ enum {
|
|||
|
||||
typedef uint8_t resolv_status_t;
|
||||
|
||||
/* Functions. */
|
||||
CCIF resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr);
|
||||
|
||||
CCIF void resolv_query(const char *name);
|
||||
|
|
|
@ -142,7 +142,7 @@ int simple_udp_sendto(struct simple_udp_connection *c,
|
|||
* \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
|
||||
* \param port The UDP port of the receiver, in host byte order
|
||||
* \param to_port The UDP port of the receiver, in host byte order
|
||||
*
|
||||
* This function sends a UDP packet to a specified IP
|
||||
* address and UDP port. The packet will be sent with the
|
||||
|
|
234
core/net/ip/uip-nameserver.c
Normal file
234
core/net/ip/uip-nameserver.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* uIP Name Server interface
|
||||
* \author Víctor Ariño <victor.arino@tado.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, tado° GmbH.
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
|
||||
#include "lib/list.h"
|
||||
#include "lib/memb.h"
|
||||
|
||||
#include <string.h>
|
||||
/** \brief Nameserver record */
|
||||
typedef struct uip_nameserver_record {
|
||||
struct uip_nameserver_record *next;
|
||||
uip_ipaddr_t ip;
|
||||
uint32_t added;
|
||||
uint32_t lifetime;
|
||||
} uip_nameserver_record;
|
||||
|
||||
/** \brief Initialization flag */
|
||||
static uint8_t initialized = 0;
|
||||
|
||||
/** \name List and memory block
|
||||
* @{
|
||||
*/
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
LIST(dns);
|
||||
MEMB(dnsmemb, uip_nameserver_record, UIP_NAMESERVER_POOL_SIZE);
|
||||
#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
static uip_ipaddr_t serveraddr;
|
||||
static uint32_t serverlifetime;
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
/** @} */
|
||||
|
||||
/** \brief Expiration time in seconds */
|
||||
#define DNS_EXPIRATION(r) \
|
||||
(((UIP_NAMESERVER_INFINITE_LIFETIME - r->added) <= r->lifetime) ? \
|
||||
UIP_NAMESERVER_INFINITE_LIFETIME : r->added + r->lifetime)
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Initialize the module variables
|
||||
*/
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
static CC_INLINE void
|
||||
init(void)
|
||||
{
|
||||
list_init(dns);
|
||||
memb_init(&dnsmemb);
|
||||
initialized = 1;
|
||||
}
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime)
|
||||
{
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
register uip_nameserver_record *e;
|
||||
|
||||
if(initialized == 0) {
|
||||
init();
|
||||
}
|
||||
|
||||
for(e = list_head(dns); e != NULL; e = list_item_next(e)) {
|
||||
if(uip_ipaddr_cmp(&e->ip, nameserver)) {
|
||||
break;
|
||||
/* RFC6106: In case there's no more space, the new servers should replace
|
||||
* the the eldest ones */
|
||||
}
|
||||
}
|
||||
|
||||
if(e == NULL) {
|
||||
if((e = memb_alloc(&dnsmemb)) != NULL) {
|
||||
list_add(dns, e);
|
||||
} else {
|
||||
uip_nameserver_record *p;
|
||||
for(e = list_head(dns), p = list_head(dns); p != NULL;
|
||||
p = list_item_next(p)) {
|
||||
if(DNS_EXPIRATION(p) < DNS_EXPIRATION(e)) {
|
||||
e = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RFC6106: In case the entry is existing the expiration time must be
|
||||
* updated. Otherwise, new entries are added. */
|
||||
if(e != NULL) {
|
||||
if(lifetime == 0) {
|
||||
memb_free(&dnsmemb, e);
|
||||
list_remove(dns, e);
|
||||
} else {
|
||||
e->added = clock_seconds();
|
||||
e->lifetime = lifetime;
|
||||
uip_ipaddr_copy(&e->ip, nameserver);
|
||||
}
|
||||
}
|
||||
#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
uip_ipaddr_copy(&serveraddr, nameserver);
|
||||
serverlifetime = lifetime;
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
/**
|
||||
* Purge expired records
|
||||
*/
|
||||
static void
|
||||
purge(void)
|
||||
{
|
||||
register uip_nameserver_record *e = NULL;
|
||||
uint32_t time = clock_seconds();
|
||||
for(e = list_head(dns); e != NULL; e = list_item_next(e)) {
|
||||
if(DNS_EXPIRATION(e) < time) {
|
||||
list_remove(dns, e);
|
||||
memb_free(&dnsmemb, e);
|
||||
e = list_head(dns);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uip_ipaddr_t *
|
||||
uip_nameserver_get(uint8_t num)
|
||||
{
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
uint8_t i;
|
||||
uip_nameserver_record *e = NULL;
|
||||
|
||||
if(initialized == 0) {
|
||||
return NULL;
|
||||
}
|
||||
purge();
|
||||
for(i = 1, e = list_head(dns); e != NULL && i <= num;
|
||||
i++, e = list_item_next(e)) {
|
||||
}
|
||||
|
||||
if(e != NULL) {
|
||||
return &e->ip;
|
||||
}
|
||||
return NULL;
|
||||
#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
if(num > 0) {
|
||||
return NULL;
|
||||
}
|
||||
return &serveraddr;
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint32_t
|
||||
uip_nameserver_next_expiration(void)
|
||||
{
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
register uip_nameserver_record *e = NULL;
|
||||
uint32_t exp = UIP_NAMESERVER_INFINITE_LIFETIME;
|
||||
uint32_t t;
|
||||
|
||||
if(initialized == 0 || list_length(dns) == 0) {
|
||||
return 0;
|
||||
}
|
||||
purge();
|
||||
for(e = list_head(dns); e != NULL; e = list_item_next(e)) {
|
||||
t = DNS_EXPIRATION(e);
|
||||
if(t < exp) {
|
||||
exp = t;
|
||||
}
|
||||
}
|
||||
|
||||
return exp;
|
||||
#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
return serverlifetime;
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint16_t
|
||||
uip_nameserver_count(void)
|
||||
{
|
||||
#if UIP_NAMESERVER_POOL_SIZE > 1
|
||||
if(initialized == 0) {
|
||||
return 0;
|
||||
}
|
||||
return list_length(dns);
|
||||
#else /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
if(uip_is_addr_unspecified(&serveraddr)) {
|
||||
#else /* NETSTACK_CONF_WITH_IPV6 */
|
||||
if(uip_ipaddr_cmp(&serveraddr, &uip_all_zeroes_addr)) {
|
||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @} */
|
101
core/net/ip/uip-nameserver.h
Normal file
101
core/net/ip/uip-nameserver.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* uIP Name Server interface
|
||||
* \author Víctor Ariño <victor.arino@tado.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, tado° GmbH.
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UIP_NAMESERVER_H_
|
||||
#define UIP_NAMESERVER_H_
|
||||
|
||||
/**
|
||||
* \name General
|
||||
* @{
|
||||
*/
|
||||
/** \brief Number of Nameservers to keep */
|
||||
#ifndef UIP_CONF_NAMESERVER_POOL_SIZE
|
||||
#define UIP_NAMESERVER_POOL_SIZE 1
|
||||
#else /* UIP_CONF_NAMESERVER_POOL_SIZE */
|
||||
#define UIP_NAMESERVER_POOL_SIZE UIP_CONF_NAMESERVER_POOL_SIZE
|
||||
#endif /* UIP_CONF_NAMESERVER_POOL_SIZE */
|
||||
/** \brief Infinite Lifetime indicator */
|
||||
#define UIP_NAMESERVER_INFINITE_LIFETIME 0xFFFFFFFF
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name Nameserver maintenance
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \brief Insert or update a nameserver into/from the pool
|
||||
*
|
||||
* The list is kept according to the RFC6106, which indicates that new entries
|
||||
* will replace old ones (with lower lifetime) and existing entries will update
|
||||
* their lifetimes.
|
||||
*
|
||||
* \param nameserver Pointer to the nameserver ip address
|
||||
* \param lifetime Life time of the given address. Minimum is 0, which is
|
||||
* considered to remove an entry. Maximum is 0xFFFFFFFF which
|
||||
* is considered infinite.
|
||||
*/
|
||||
void uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime);
|
||||
|
||||
/**
|
||||
* \brief Get a Nameserver ip address given in RA
|
||||
*
|
||||
* \param num The number of the nameserver to obtain, starting at 0 and going
|
||||
* up to the pool size.
|
||||
*/
|
||||
uip_ipaddr_t *uip_nameserver_get(uint8_t num);
|
||||
|
||||
/**
|
||||
* \brief Get next expiration time
|
||||
*
|
||||
* The least expiration time is returned
|
||||
*/
|
||||
uint32_t uip_nameserver_next_expiration(void);
|
||||
|
||||
/**
|
||||
* \brief Get the number of recorded name servers
|
||||
*/
|
||||
uint16_t uip_nameserver_count(void);
|
||||
/** @} */
|
||||
|
||||
#endif /* UIP_NAMESERVER_H_ */
|
||||
/** @} */
|
|
@ -350,7 +350,7 @@ void uip_setipid(uint16_t id);
|
|||
* Periodic processing for a connection identified by its number.
|
||||
*
|
||||
* This function does the necessary periodic processing (timers,
|
||||
* polling) for a uIP TCP conneciton, and should be called when the
|
||||
* polling) for a uIP TCP connection, and should be called when the
|
||||
* periodic uIP timer goes off. It should be called for every
|
||||
* connection, regardless of whether they are open of closed.
|
||||
*
|
||||
|
@ -393,8 +393,10 @@ void uip_setipid(uint16_t id);
|
|||
uip_process(UIP_TIMER); } while (0)
|
||||
|
||||
/**
|
||||
* Macro to determine whether a specific uIP connection is active
|
||||
*
|
||||
*
|
||||
* \param conn The connection's number
|
||||
* \retval 0 Connection closed
|
||||
*/
|
||||
#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED)
|
||||
|
||||
|
@ -489,7 +491,7 @@ void uip_reass_over(void);
|
|||
/**
|
||||
* The uIP packet buffer.
|
||||
*
|
||||
* The uip_buf array is used to hold incoming and outgoing
|
||||
* The uip_aligned_buf array is used to hold incoming and outgoing
|
||||
* packets. The device driver should place incoming data into this
|
||||
* buffer. When sending data, the device driver should read the link
|
||||
* level headers and the TCP/IP headers from this buffer. The size of
|
||||
|
@ -519,6 +521,8 @@ typedef union {
|
|||
} uip_buf_t;
|
||||
|
||||
CCIF extern uip_buf_t uip_aligned_buf;
|
||||
|
||||
/** Macro to access uip_aligned_buf as an array of bytes */
|
||||
#define uip_buf (uip_aligned_buf.u8)
|
||||
|
||||
|
||||
|
@ -1097,7 +1101,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport);
|
|||
|
||||
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check if an address is a broadcast address for a network.
|
||||
*
|
||||
* Checks if an address is the broadcast address for a network. The
|
||||
|
@ -2172,7 +2176,7 @@ CCIF extern uip_lladdr_t uip_lladdr;
|
|||
*
|
||||
* See RFC1071.
|
||||
*
|
||||
* \param buf A pointer to the buffer over which the checksum is to be
|
||||
* \param data A pointer to the buffer over which the checksum is to be
|
||||
* computed.
|
||||
*
|
||||
* \param len The length of the buffer over which the checksum is to
|
||||
|
@ -2180,7 +2184,7 @@ CCIF extern uip_lladdr_t uip_lladdr;
|
|||
*
|
||||
* \return The Internet checksum of the buffer.
|
||||
*/
|
||||
uint16_t uip_chksum(uint16_t *buf, uint16_t len);
|
||||
uint16_t uip_chksum(uint16_t *data, uint16_t len);
|
||||
|
||||
/**
|
||||
* Calculate the IP header checksum of the packet header in uip_buf.
|
||||
|
|
|
@ -93,7 +93,7 @@ void uip_add32(uint8_t *op32, uint16_t op16);
|
|||
* \note This function is not called in the current version of uIP,
|
||||
* but future versions might make use of it.
|
||||
*
|
||||
* \param buf A pointer to the buffer over which the checksum is to be
|
||||
* \param data A pointer to the buffer over which the checksum is to be
|
||||
* computed.
|
||||
*
|
||||
* \param len The length of the buffer over which the checksum is to
|
||||
|
@ -101,7 +101,7 @@ void uip_add32(uint8_t *op32, uint16_t op16);
|
|||
*
|
||||
* \return The Internet checksum of the buffer.
|
||||
*/
|
||||
uint16_t uip_chksum(uint16_t *buf, uint16_t len);
|
||||
uint16_t uip_chksum(uint16_t *data, uint16_t len);
|
||||
|
||||
/**
|
||||
* Calculate the IP header checksum of the packet header in uip_buf.
|
||||
|
|
|
@ -75,18 +75,9 @@
|
|||
#include "net/ipv4/uip_arp.h"
|
||||
#include "net/ip/uip_arch.h"
|
||||
|
||||
#if !NETSTACK_CONF_WITH_IPV6 /* If NETSTACK_CONF_WITH_IPV6 is defined, we compile the
|
||||
uip6.c file instead of this one. Therefore
|
||||
this #ifndef removes the entire compilation
|
||||
output of the uip.c file */
|
||||
|
||||
|
||||
#if NETSTACK_CONF_WITH_IPV6
|
||||
#include "net/ipv4/uip-neighbor.h"
|
||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Variable definitions. */
|
||||
|
||||
|
@ -699,7 +690,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
goto drop;
|
||||
|
||||
/* Check if we were invoked because of the perodic timer fireing. */
|
||||
/* Check if we were invoked because of the periodic timer firing. */
|
||||
} else if(flag == UIP_TIMER) {
|
||||
#if UIP_REASSEMBLY
|
||||
if(uip_reasstmr != 0) {
|
||||
|
@ -851,7 +842,7 @@ uip_process(uint8_t flag)
|
|||
that the packet has been corrupted in transit. If the size of
|
||||
uip_len is larger than the size reported in the IP packet header,
|
||||
the packet has been padded and we set uip_len to the correct
|
||||
value.. */
|
||||
value. */
|
||||
|
||||
if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
|
||||
uip_len = (BUF->len[0] << 8) + BUF->len[1];
|
||||
|
@ -891,7 +882,7 @@ uip_process(uint8_t flag)
|
|||
|
||||
if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) {
|
||||
/* If we are configured to use ping IP address configuration and
|
||||
hasn't been assigned an IP address yet, we accept all ICMP
|
||||
haven't been assigned an IP address yet, we accept all ICMP
|
||||
packets. */
|
||||
#if UIP_PINGADDRCONF && !NETSTACK_CONF_WITH_IPV6
|
||||
if(BUF->proto == UIP_PROTO_ICMP) {
|
||||
|
@ -1252,7 +1243,7 @@ uip_process(uint8_t flag)
|
|||
}
|
||||
}
|
||||
|
||||
/* If we didn't find and active connection that expected the packet,
|
||||
/* If we didn't find an active connection that expected the packet,
|
||||
either this packet is an old duplicate, or this is a SYN packet
|
||||
destined for a connection in LISTEN. If the SYN flag isn't set,
|
||||
it is an old packet and we send a RST. */
|
||||
|
@ -1441,7 +1432,7 @@ uip_process(uint8_t flag)
|
|||
uip_flags = 0;
|
||||
/* We do a very naive form of TCP reset processing; we just accept
|
||||
any RST and kill our connection. We should in fact check if the
|
||||
sequence number of this reset is wihtin our advertised window
|
||||
sequence number of this reset is within our advertised window
|
||||
before we accept the reset. */
|
||||
if(BUF->flags & TCP_RST) {
|
||||
uip_connr->tcpstateflags = UIP_CLOSED;
|
||||
|
@ -1973,6 +1964,4 @@ uip_send(const void *data, int len)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* NETSTACK_CONF_WITH_IPV6 */
|
||||
|
||||
/** @}*/
|
||||
|
|
|
@ -29,20 +29,15 @@
|
|||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup roll-tm
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* This file implements IPv6 MCAST forwarding according to the
|
||||
* algorithm described in the "MCAST Forwarding Using Trickle"
|
||||
* internet draft.
|
||||
*
|
||||
* The current version of the draft can always be found in
|
||||
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
|
||||
*
|
||||
* This implementation is based on the draft version stored in
|
||||
* ROLL_TM_VER
|
||||
*
|
||||
* Implementation of the ROLL TM multicast engine
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
|
@ -1440,6 +1435,9 @@ init()
|
|||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief The ROLL TM engine driver
|
||||
*/
|
||||
const struct uip_mcast6_driver roll_tm_driver = {
|
||||
"ROLL TM",
|
||||
init,
|
||||
|
@ -1447,3 +1445,4 @@ const struct uip_mcast6_driver roll_tm_driver = {
|
|||
in,
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -29,25 +29,34 @@
|
|||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \defgroup roll-tm ROLL Trickle Multicast
|
||||
*
|
||||
* IPv6 multicast according to the algorithm in the
|
||||
* "MCAST Forwarding Using Trickle" internet draft.
|
||||
*
|
||||
* The current version of the draft can always be found in
|
||||
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
|
||||
*
|
||||
* This implementation is based on the draft version stored in
|
||||
* ROLL_TM_VER.
|
||||
*
|
||||
* In draft v2, the document was renamed to
|
||||
* "Multicast Protocol for Low power and Lossy Networks (MPL)"
|
||||
* Due to very significant changes between draft versions 1 and 2,
|
||||
* MPL will be implemented as a separate engine and this file here
|
||||
* will provide legacy support for Draft v1.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Header file for IPv6 multicast according to the algorithm in the
|
||||
* "MCAST Forwarding Using Trickle" internet draft.
|
||||
*
|
||||
* The current version of the draft can always be found in
|
||||
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
|
||||
*
|
||||
* This implementation is based on the draft version stored in
|
||||
* ROLL_TM_VER.
|
||||
*
|
||||
* In draft v2, the document was renamed to
|
||||
* "Multicast Protocol for Low power and Lossy Networks (MPL)"
|
||||
* Due to very significant changes between draft versions 1 and 2,
|
||||
* MPL will be implemented as a separate engine and this file here
|
||||
* will provide legacy support for Draft v1.
|
||||
*
|
||||
* Header file for the implementation of the ROLL-TM multicast engine
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#ifndef ROLL_TM_H_
|
||||
|
@ -60,9 +69,9 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Protocol Constants */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define ROLL_TM_VER 1 /* Supported Draft Version */
|
||||
#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */
|
||||
#define ROLL_TM_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */
|
||||
#define ROLL_TM_VER 1 /**< Supported Draft Version */
|
||||
#define ROLL_TM_ICMP_CODE 0 /**< ROLL TM ICMPv6 code field */
|
||||
#define ROLL_TM_IP_HOP_LIMIT 0xFF /**< Hop limit for ICMP messages */
|
||||
#define ROLL_TM_INFINITE_REDUNDANCY 0xFF
|
||||
#define ROLL_TM_DGRAM_OUT 0
|
||||
#define ROLL_TM_DGRAM_IN 1
|
||||
|
@ -153,7 +162,7 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Configuration */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
/**
|
||||
* Number of Sliding Windows
|
||||
* In essence: How many unique sources of simultaneous multicast traffic do we
|
||||
* want to support for our lowpan
|
||||
|
@ -166,7 +175,7 @@
|
|||
#define ROLL_TM_WINS 2
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
/**
|
||||
* Maximum Number of Buffered Multicast Messages
|
||||
* This buffer is shared across all Seed IDs, therefore a new very active Seed
|
||||
* may eventually occupy all slots. It would make little sense (if any) to
|
||||
|
@ -178,7 +187,7 @@
|
|||
#define ROLL_TM_BUFF_NUM 6
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
/**
|
||||
* Use Short Seed IDs [short: 2, long: 16 (default)]
|
||||
* It can be argued that we should (and it would be easy to) support both at
|
||||
* the same time but the draft doesn't list this as a MUST so we opt for
|
||||
|
@ -190,7 +199,7 @@
|
|||
#define ROLL_TM_SHORT_SEEDS 0
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
/**
|
||||
* Destination address for our ICMPv6 advertisements. The draft gives us a
|
||||
* choice between LL all-nodes or LL all-routers
|
||||
*
|
||||
|
@ -202,7 +211,7 @@
|
|||
#define ROLL_TM_DEST_ALL_NODES 0
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
/**
|
||||
* M param for our outgoing messages
|
||||
* By default, we set the M bit (conservative). Define this as 0 to clear the
|
||||
* M bit in our outgoing messages (aggressive)
|
||||
|
@ -215,10 +224,21 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Stats datatype */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Multicast stats extension for the ROLL TM engine
|
||||
*/
|
||||
struct roll_tm_stats {
|
||||
/** Number of received ICMP datagrams */
|
||||
UIP_MCAST6_STATS_DATATYPE icmp_in;
|
||||
|
||||
/** Number of ICMP datagrams sent */
|
||||
UIP_MCAST6_STATS_DATATYPE icmp_out;
|
||||
|
||||
/** Number of malformed ICMP datagrams seen by us */
|
||||
UIP_MCAST6_STATS_DATATYPE icmp_bad;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* ROLL_TM_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
|
@ -29,14 +29,16 @@
|
|||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup smrf-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
|
||||
*
|
||||
* It will only work in RPL networks in MOP 3 "Storing with Multicast"
|
||||
* This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
|
@ -199,6 +201,9 @@ out()
|
|||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief The SMRF engine driver
|
||||
*/
|
||||
const struct uip_mcast6_driver smrf_driver = {
|
||||
"SMRF",
|
||||
init,
|
||||
|
@ -206,3 +211,4 @@ const struct uip_mcast6_driver smrf_driver = {
|
|||
in,
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -29,12 +29,22 @@
|
|||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \defgroup smrf-multicast 'Stateless Multicast RPL Forwarding' (SMRF)
|
||||
*
|
||||
* SMRF will only work in RPL networks in MOP 3 "Storing with Multicast"
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Header file for 'Stateless Multicast RPL Forwarding' (SMRF)
|
||||
* Header file for the SMRF forwarding engine
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#ifndef SMRF_H_
|
||||
|
@ -71,5 +81,8 @@ struct smrf_stats {
|
|||
uint16_t mcast_bad;
|
||||
uint16_t mcast_dropped;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* SMRF_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
|
@ -29,22 +29,27 @@
|
|||
* This file is part of the Contiki operating system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Header file with definition of multicast engine constants
|
||||
* Header file with definition of multicast engine constants
|
||||
*
|
||||
* When writing a new engine, add it here with a unique number and
|
||||
* then modify uip-mcast6.h accordingly
|
||||
* When writing a new engine, add it here with a unique number and
|
||||
* then modify uip-mcast6.h accordingly
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#ifndef UIP_MCAST6_ENGINES_H_
|
||||
#define UIP_MCAST6_ENGINES_H_
|
||||
|
||||
#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */
|
||||
#define UIP_MCAST6_ENGINE_SMRF 1
|
||||
#define UIP_MCAST6_ENGINE_ROLL_TM 2
|
||||
#define UIP_MCAST6_ENGINE_NONE 0 /**< Selecting this disables mcast */
|
||||
#define UIP_MCAST6_ENGINE_SMRF 1 /**< The SMRF engine */
|
||||
#define UIP_MCAST6_ENGINE_ROLL_TM 2 /**< The ROLL TM engine */
|
||||
|
||||
#endif /* UIP_MCAST6_ENGINES_H_ */
|
||||
/** @} */
|
||||
|
|
|
@ -28,12 +28,16 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Multicast routing table manipulation
|
||||
* Multicast routing table manipulation
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
|
@ -128,3 +132,4 @@ uip_mcast6_route_init()
|
|||
list_init(mcast_route_list);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -28,12 +28,16 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Multicast routing table manipulation
|
||||
* Header file for multicast routing table manipulation
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
#ifndef UIP_MCAST6_ROUTE_H_
|
||||
#define UIP_MCAST6_ROUTE_H_
|
||||
|
@ -45,18 +49,48 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/** \brief An entry in the multicast routing table */
|
||||
typedef struct uip_mcast6_route {
|
||||
struct uip_mcast6_route *next;
|
||||
uip_ipaddr_t group;
|
||||
uint32_t lifetime; /* seconds */
|
||||
void *dag; /* Pointer to an rpl_dag_t struct */
|
||||
struct uip_mcast6_route *next; /**< Routes are arranged in a linked list */
|
||||
uip_ipaddr_t group; /**< The multicast group */
|
||||
uint32_t lifetime; /**< Entry lifetime seconds */
|
||||
void *dag; /**< Pointer to an rpl_dag_t struct */
|
||||
} uip_mcast6_route_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name Multicast Routing Table Manipulation */
|
||||
/** @{ */
|
||||
|
||||
/**
|
||||
* \brief Lookup a multicast route
|
||||
* \param group A pointer to the multicast group to be searched for
|
||||
* \return A pointer to the new routing entry, or NULL if the route could not
|
||||
* be found
|
||||
*/
|
||||
uip_mcast6_route_t *uip_mcast6_route_lookup(uip_ipaddr_t *group);
|
||||
|
||||
/**
|
||||
* \brief Add a multicast route
|
||||
* \param group A pointer to the multicast group to be added
|
||||
* \return A pointer to the new route, or NULL if the route could not be added
|
||||
*/
|
||||
uip_mcast6_route_t *uip_mcast6_route_add(uip_ipaddr_t *group);
|
||||
void uip_mcast6_route_rm(uip_mcast6_route_t *defrt);
|
||||
|
||||
/**
|
||||
* \brief Remove a multicast route
|
||||
* \param route A pointer to the route to be removed
|
||||
*/
|
||||
void uip_mcast6_route_rm(uip_mcast6_route_t *route);
|
||||
|
||||
/**
|
||||
* \brief Retrieve the count of multicast routes
|
||||
* \return The number of multicast routes
|
||||
*/
|
||||
int uip_mcast6_route_count(void);
|
||||
|
||||
/**
|
||||
* \brief Retrieve a pointer to the start of the multicast routes list
|
||||
* \return A pointer to the start of the multicast routes
|
||||
*
|
||||
* If the multicast routes list is empty, this function will return NULL
|
||||
*/
|
||||
uip_mcast6_route_t *uip_mcast6_route_list_head(void);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
@ -73,3 +107,4 @@ void uip_mcast6_route_init(void);
|
|||
/** @} */
|
||||
|
||||
#endif /* UIP_MCAST6_ROUTE_H_ */
|
||||
/** @} */
|
||||
|
|
|
@ -27,12 +27,16 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* IPv6 multicast forwarding stats maintenance
|
||||
* IPv6 multicast forwarding stats maintenance
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
#include "net/ipv6/multicast/uip-mcast6-stats.h"
|
||||
|
||||
|
@ -47,3 +51,4 @@ uip_mcast6_stats_init(void *stats)
|
|||
uip_mcast6_stats.engine_stats = stats;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -27,12 +27,16 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip6-multicast
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Header file for IPv6 multicast forwarding stats maintenance
|
||||
* Header file for IPv6 multicast forwarding stats maintenance
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
#ifndef UIP_MCAST6_STATS_H_
|
||||
#define UIP_MCAST6_STATS_H_
|
||||
|
@ -56,15 +60,35 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Stats datatype */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief A data structure used to maintain multicast stats
|
||||
*
|
||||
* Each engine can extend this structure via the engine_stats field
|
||||
*/
|
||||
typedef struct uip_mcast6_stats {
|
||||
/** Count of unique datagrams received */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_in_unique;
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_in_all; /* At layer 3 */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_in_ours; /* Unique and we are a group member */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_fwd; /* Forwarded by us but we are not the seed */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_out; /* We are the seed */
|
||||
|
||||
/** Count of all datagrams received */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_in_all;
|
||||
|
||||
/** Count of datagrams received for a group that we have joined */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_in_ours;
|
||||
|
||||
/** Count of datagrams forwarded by us but we are not the seed */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_fwd;
|
||||
|
||||
/** Count of multicast datagrams originated by us */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_out;
|
||||
|
||||
/** Count of malformed multicast datagrams seen by us */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_bad;
|
||||
|
||||
/** Count of multicast datagrams correclty formed but dropped by us */
|
||||
UIP_MCAST6_STATS_DATATYPE mcast_dropped;
|
||||
void *engine_stats; /* Opaque pointer to an engine's additional stats */
|
||||
|
||||
/** Opaque pointer to an engine's additional stats */
|
||||
void *engine_stats;
|
||||
} uip_mcast6_stats_t;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Access macros */
|
||||
|
@ -89,3 +113,5 @@ extern uip_mcast6_stats_t uip_mcast6_stats;
|
|||
void uip_mcast6_stats_init(void *stats);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* UIP_MCAST6_STATS_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* This header file contains configuration directives for uIPv6
|
||||
* multicast support.
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \defgroup uip6-multicast IPv6 Multicast Forwarding
|
||||
*
|
||||
* We currently support 2 engines:
|
||||
* - 'Stateless Multicast RPL Forwarding' (SMRF)
|
||||
|
@ -42,6 +44,14 @@
|
|||
* in the internet draft:
|
||||
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* This header file contains configuration directives for uIPv6
|
||||
* multicast support.
|
||||
*
|
||||
* \author
|
||||
* George Oikonomou - <oikonomou@users.sourceforge.net>
|
||||
*/
|
||||
|
@ -83,7 +93,11 @@
|
|||
* Multicast API. Similar to NETSTACK, each engine must define a driver and
|
||||
* populate the fields with suitable function pointers
|
||||
*/
|
||||
/**
|
||||
* \brief The data structure used to represent a multicast engine
|
||||
*/
|
||||
struct uip_mcast6_driver {
|
||||
/** The driver's name */
|
||||
char *name;
|
||||
|
||||
/** Initialize the multicast engine */
|
||||
|
@ -110,6 +124,7 @@ struct uip_mcast6_driver {
|
|||
*
|
||||
* \return 0: Drop, 1: Deliver
|
||||
*
|
||||
*
|
||||
* When a datagram with a multicast destination address is received,
|
||||
* the forwarding logic in core is bypassed. Instead, we let the
|
||||
* multicast engine handle forwarding internally if and as necessary.
|
||||
|
@ -158,5 +173,7 @@ extern const struct uip_mcast6_driver UIP_MCAST6;
|
|||
#error "Check the value of UIP_CONF_IPV6_RPL in conf files."
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif /* UIP_MCAST6_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
|
@ -234,7 +234,7 @@ struct sicslowpan_addr_context {
|
|||
* \brief check whether we can compress the IID in
|
||||
* address 'a' to 16 bits.
|
||||
* This is used for unicast addresses only, and is true
|
||||
* if the address is on the format <PREFIX>::0000:00ff:fe00:XXXX
|
||||
* if the address is on the format \<PREFIX\>::0000:00ff:fe00:XXXX
|
||||
* NOTE: we currently assume 64-bits prefixes
|
||||
*/
|
||||
#define sicslowpan_is_iid_16_bit_compressable(a) \
|
||||
|
|
|
@ -29,20 +29,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* IPv6 Neighbor cache (link-layer/IPv6 address mapping)
|
||||
* IPv6 Neighbor cache (link-layer/IPv6 address mapping)
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
|
|
@ -29,20 +29,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* IPv6 Neighbor cache (link-layer/IPv6 address mapping)
|
||||
* IPv6 Neighbor cache (link-layer/IPv6 address mapping)
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef UIP_DS6_NEIGHBOR_H_
|
||||
#define UIP_DS6_NEIGHBOR_H_
|
||||
|
||||
|
@ -74,6 +74,7 @@ typedef struct uip_ds6_nbr {
|
|||
uint8_t nscount;
|
||||
uint8_t isrouter;
|
||||
uint8_t state;
|
||||
uint16_t link_metric;
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
struct uip_packetqueue_handle packethandle;
|
||||
#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4
|
||||
|
@ -98,12 +99,12 @@ int uip_ds6_nbr_num(void);
|
|||
|
||||
/**
|
||||
* \brief
|
||||
* This searches inside the neighbor table for the neighbor that is about to
|
||||
* expire the next.
|
||||
* This searches inside the neighbor table for the neighbor that is about to
|
||||
* expire the next.
|
||||
*
|
||||
* \return
|
||||
* A reference to the neighbor about to expire the next or NULL if
|
||||
* table is empty.
|
||||
* A reference to the neighbor about to expire the next or NULL if
|
||||
* table is empty.
|
||||
*/
|
||||
uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void);
|
||||
|
||||
|
|
|
@ -29,6 +29,15 @@
|
|||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Routing table manipulation
|
||||
*/
|
||||
#include "net/ipv6/uip-ds6.h"
|
||||
#include "net/ip/uip.h"
|
||||
|
||||
|
@ -269,9 +278,16 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
|||
one first. */
|
||||
r = uip_ds6_route_lookup(ipaddr);
|
||||
if(r != NULL) {
|
||||
uip_ipaddr_t *current_nexthop;
|
||||
current_nexthop = uip_ds6_route_nexthop(r);
|
||||
if(uip_ipaddr_cmp(nexthop, current_nexthop)) {
|
||||
/* no need to update route - already correct! */
|
||||
return r;
|
||||
}
|
||||
PRINTF("uip_ds6_route_add: old route for ");
|
||||
PRINT6ADDR(ipaddr);
|
||||
PRINTF(" found, deleting it\n");
|
||||
|
||||
uip_ds6_route_rm(r);
|
||||
}
|
||||
{
|
||||
|
@ -629,3 +645,4 @@ uip_ds6_defrt_periodic(void)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @} */
|
||||
|
|
|
@ -29,6 +29,14 @@
|
|||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Header file for routing table manipulation
|
||||
*/
|
||||
#ifndef UIP_DS6_ROUTE_H
|
||||
#define UIP_DS6_ROUTE_H
|
||||
|
||||
|
@ -158,3 +166,4 @@ uip_ds6_route_t *uip_ds6_route_next(uip_ds6_route_t *);
|
|||
/** @} */
|
||||
|
||||
#endif /* UIP_DS6_ROUTE_H */
|
||||
/** @} */
|
||||
|
|
|
@ -29,17 +29,17 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* IPv6 data structures handling functions.
|
||||
* Comprises part of the Neighbor discovery (RFC 4861)
|
||||
* and auto configuration (RFC 4862) state machines.
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
* \file
|
||||
* IPv6 data structure manipulation.
|
||||
* Comprises part of the Neighbor discovery (RFC 4861)
|
||||
* and auto configuration (RFC 4862) state machines.
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
/**
|
||||
* \file
|
||||
* Network interface and stateless autoconfiguration (RFC 4862)
|
||||
* Header file for IPv6-related data structures
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
*
|
||||
|
|
|
@ -31,15 +31,15 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* ICMPv6 echo request and error messages (RFC 4443)
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
* \file
|
||||
* ICMPv6 (RFC 4443) implementation, with message and error handling
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
|
|
@ -31,15 +31,15 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* ICMPv6 echo request and error messages (RFC 4443)
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
* \file
|
||||
* Header file for ICMPv6 message and error handing (RFC 4443)
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
*/
|
||||
|
||||
#ifndef ICMP6_H_
|
||||
|
|
|
@ -57,21 +57,22 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Neighbor discovery (RFC 4861)
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
* \file
|
||||
* Neighbor discovery (RFC 4861)
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "net/ipv6/uip-icmp6.h"
|
||||
#include "net/ipv6/uip-nd6.h"
|
||||
#include "net/ipv6/uip-ds6.h"
|
||||
#include "net/ip/uip-nameserver.h"
|
||||
#include "lib/random.h"
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
@ -112,6 +113,7 @@ void uip_log(char *msg);
|
|||
#define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
|
||||
#define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
|
||||
#define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
|
||||
#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
|
||||
/** @} */
|
||||
|
||||
static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/
|
||||
|
@ -715,6 +717,29 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
|
|||
|
||||
uip_len += UIP_ND6_OPT_MTU_LEN;
|
||||
nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
|
||||
|
||||
#if UIP_ND6_RA_RDNSS
|
||||
if(uip_nameserver_count() > 0) {
|
||||
uint8_t i = 0;
|
||||
uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip;
|
||||
uip_ipaddr_t *dns = NULL;
|
||||
UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS;
|
||||
UIP_ND6_OPT_RDNSS_BUF->reserved = 0;
|
||||
UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration();
|
||||
if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
|
||||
UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds();
|
||||
}
|
||||
while((dns = uip_nameserver_get(i)) != NULL) {
|
||||
uip_ipaddr_copy(ip++, dns);
|
||||
i++;
|
||||
}
|
||||
UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
|
||||
PRINTF("%d nameservers reported\n", i);
|
||||
uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3;
|
||||
nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3;
|
||||
}
|
||||
#endif /* UIP_ND6_RA_RDNSS */
|
||||
|
||||
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
|
||||
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
|
||||
|
||||
|
@ -938,6 +963,23 @@ ra_input(void)
|
|||
/* End of autonomous flag related processing */
|
||||
}
|
||||
break;
|
||||
#if UIP_ND6_RA_RDNSS
|
||||
case UIP_ND6_OPT_RDNSS:
|
||||
if(UIP_ND6_RA_BUF->flags_reserved & (UIP_ND6_O_FLAG << 6)) {
|
||||
PRINTF("Processing RDNSS option\n");
|
||||
uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2;
|
||||
uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip);
|
||||
PRINTF("got %d nameservers\n", naddr);
|
||||
while(naddr-- > 0) {
|
||||
PRINTF(" nameserver: ");
|
||||
PRINT6ADDR(ip);
|
||||
PRINTF(" lifetime: %lx\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
|
||||
uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
|
||||
ip++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* UIP_ND6_RA_RDNSS */
|
||||
default:
|
||||
PRINTF("ND option not supported in RA");
|
||||
break;
|
||||
|
|
|
@ -31,15 +31,15 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Neighbor discovery (RFC 4861)
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
* \file
|
||||
* Header file for IPv6 Neighbor discovery (RFC 4861)
|
||||
* \author Julien Abeille <jabeille@cisco.com>
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com>
|
||||
*/
|
||||
|
||||
#ifndef UIP_ND6_H_
|
||||
|
@ -87,7 +87,7 @@
|
|||
#define UIP_ND6_MIN_RA_INTERVAL UIP_CONF_ND6_MIN_RA_INTERVAL
|
||||
#endif
|
||||
#define UIP_ND6_M_FLAG 0
|
||||
#define UIP_ND6_O_FLAG 0
|
||||
#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL)
|
||||
#define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL
|
||||
|
||||
#define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/
|
||||
|
@ -139,6 +139,23 @@
|
|||
/** @} */
|
||||
|
||||
|
||||
/** \name RFC 6106 RA DNS Options Constants */
|
||||
/** @{ */
|
||||
#ifndef UIP_CONF_ND6_RA_RDNSS
|
||||
#define UIP_ND6_RA_RDNSS 0
|
||||
#else
|
||||
#define UIP_ND6_RA_RDNSS UIP_CONF_ND6_RA_RDNSS
|
||||
#endif
|
||||
|
||||
#ifndef UIP_CONF_ND6_RA_DNSSL
|
||||
#define UIP_ND6_RA_DNSSL 0
|
||||
#else
|
||||
#error Not implemented
|
||||
#define UIP_ND6_RA_DNSSL UIP_CONF_ND6_RA_DNSSL
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
|
||||
/** \name ND6 option types */
|
||||
/** @{ */
|
||||
#define UIP_ND6_OPT_SLLAO 1
|
||||
|
@ -146,6 +163,8 @@
|
|||
#define UIP_ND6_OPT_PREFIX_INFO 3
|
||||
#define UIP_ND6_OPT_REDIRECTED_HDR 4
|
||||
#define UIP_ND6_OPT_MTU 5
|
||||
#define UIP_ND6_OPT_RDNSS 25
|
||||
#define UIP_ND6_OPT_DNSSL 31
|
||||
/** @} */
|
||||
|
||||
/** \name ND6 option types */
|
||||
|
@ -168,6 +187,8 @@
|
|||
#define UIP_ND6_OPT_HDR_LEN 2
|
||||
#define UIP_ND6_OPT_PREFIX_INFO_LEN 32
|
||||
#define UIP_ND6_OPT_MTU_LEN 8
|
||||
#define UIP_ND6_OPT_RDNSS_LEN 1
|
||||
#define UIP_ND6_OPT_DNSSL_LEN 1
|
||||
|
||||
|
||||
/* Length of TLLAO and SLLAO options, it is L2 dependant */
|
||||
|
@ -290,6 +311,15 @@ typedef struct uip_nd6_opt_mtu {
|
|||
uint32_t mtu;
|
||||
} uip_nd6_opt_mtu;
|
||||
|
||||
/** \brief ND option RDNSS */
|
||||
typedef struct uip_nd6_opt_dns {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
uint16_t reserved;
|
||||
uint32_t lifetime;
|
||||
uip_ipaddr_t ip;
|
||||
} uip_nd6_opt_dns;
|
||||
|
||||
/** \struct Redirected header option */
|
||||
typedef struct uip_nd6_opt_redirected_hdr {
|
||||
uint8_t type;
|
||||
|
|
|
@ -31,20 +31,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* The uIP TCP/IPv6 stack code.
|
||||
* The uIP TCP/IPv6 stack code.
|
||||
*
|
||||
* \author Adam Dunkels <adam@sics.se>
|
||||
* \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
|
||||
* \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uip6
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* uIP is a small implementation of the IP, UDP and TCP protocols (as
|
||||
* well as some basic ICMP stuff). The implementation couples the IP,
|
||||
|
@ -105,7 +105,10 @@ struct uip_stats uip_stat;
|
|||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @{ \name Layer 2 variables */
|
||||
/**
|
||||
* \name Layer 2 variables
|
||||
* @{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** Host L2 address */
|
||||
#if UIP_CONF_LL_802154
|
||||
|
@ -116,7 +119,10 @@ uip_lladdr_t uip_lladdr = {{0x00,0x06,0x98,0x00,0x02,0x32}};
|
|||
/** @} */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @{ \name Layer 3 variables */
|
||||
/**
|
||||
* \name Layer 3 variables
|
||||
* @{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Type of the next header in IPv6 header or extension headers
|
||||
|
@ -141,8 +147,9 @@ uint8_t uip_ext_opt_offset = 0;
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* Buffers */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name Buffer defines
|
||||
* @{
|
||||
/**
|
||||
* \name Buffer defines
|
||||
* @{
|
||||
*/
|
||||
#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
|
||||
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
@ -161,8 +168,9 @@ uint8_t uip_ext_opt_offset = 0;
|
|||
#endif /* UIP_CONF_IPV6_RPL */
|
||||
#define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len])
|
||||
/** @} */
|
||||
/** \name Buffer variables
|
||||
* @{
|
||||
/**
|
||||
* \name Buffer variables
|
||||
* @{
|
||||
*/
|
||||
/** Packet buffer for incoming and outgoing packets */
|
||||
#ifndef UIP_CONF_EXTERNAL_BUFFER
|
||||
|
@ -185,7 +193,10 @@ uint16_t uip_len, uip_slen;
|
|||
/** @} */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @{ \name General variables */
|
||||
/**
|
||||
* \name General variables
|
||||
* @{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* The uip_flags variable is used for communication between the TCP/IP stack
|
||||
|
@ -209,7 +220,8 @@ static uint16_t lastport;
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/* TCP */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** \name TCP defines
|
||||
/**
|
||||
* \name TCP defines
|
||||
*@{
|
||||
*/
|
||||
/* Structures and definitions. */
|
||||
|
@ -227,7 +239,8 @@ static uint16_t lastport;
|
|||
|
||||
#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
|
||||
/** @} */
|
||||
/** \name TCP variables
|
||||
/**
|
||||
* \name TCP variables
|
||||
*@{
|
||||
*/
|
||||
#if UIP_TCP
|
||||
|
@ -248,7 +261,10 @@ static uint16_t tmp16;
|
|||
/** @} */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @{ \name UDP variables */
|
||||
/**
|
||||
* \name UDP variables
|
||||
* @{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_UDP
|
||||
struct uip_udp_conn *uip_udp_conn;
|
||||
|
@ -257,7 +273,10 @@ struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
|
|||
/** @} */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @{ \name ICMPv6 variables */
|
||||
/**
|
||||
* \name ICMPv6 variables
|
||||
* @{
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if UIP_CONF_ICMP6
|
||||
/** single possible icmpv6 "connection" */
|
||||
|
|
|
@ -64,12 +64,13 @@ uint32_t anti_replay_get_counter(void);
|
|||
|
||||
/**
|
||||
* \brief Initializes the anti-replay information about the sender
|
||||
* \param info Anti-replay information about the sender
|
||||
*/
|
||||
void anti_replay_init_info(struct anti_replay_info *info);
|
||||
|
||||
/**
|
||||
* \brief Checks if received frame was replayed
|
||||
* \param last_counters Anti-replay information about the sender
|
||||
* \param info Anti-replay information about the sender
|
||||
* \retval 0 <-> received frame was not replayed
|
||||
*/
|
||||
int anti_replay_was_replayed(struct anti_replay_info *info);
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \defgroup llsec802154
|
||||
* \defgroup llsec802154 Link Layer Security Common Functionality
|
||||
*
|
||||
* Common functionality of 802.15.4-compliant llsec_drivers.
|
||||
*
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \defgroup noncoresec
|
||||
* \defgroup noncoresec LLSEC driver using a network-wide key (NONCORESEC)
|
||||
*
|
||||
* Noncompromise-resilient 802.15.4 security
|
||||
*
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \defgroup nullsec
|
||||
* \defgroup nullsec LLSEC driver with zero security (NULLSEC)
|
||||
*
|
||||
* Insecure link layer security driver.
|
||||
*
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup net 802.15.4 frame creation and parsing
|
||||
* \addtogroup net
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
|
|
@ -56,10 +56,10 @@ static uint16_t buflen, bufptr;
|
|||
static uint8_t hdrptr;
|
||||
|
||||
/* The declarations below ensure that the packet buffer is aligned on
|
||||
an even 16-bit boundary. On some platforms (most notably the
|
||||
msp430), having apotentially misaligned packet buffer may lead to
|
||||
problems when accessing 16-bit values. */
|
||||
static uint16_t packetbuf_aligned[(PACKETBUF_SIZE + PACKETBUF_HDR_SIZE) / 2 + 1];
|
||||
an even 32-bit boundary. On some platforms (most notably the
|
||||
msp430 or OpenRISC), having a potentially misaligned packet buffer may lead to
|
||||
problems when accessing words. */
|
||||
static uint32_t packetbuf_aligned[(PACKETBUF_SIZE + PACKETBUF_HDR_SIZE + 3) / 4];
|
||||
static uint8_t *packetbuf = (uint8_t *)packetbuf_aligned;
|
||||
|
||||
static uint8_t *packetbufptr;
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
* The abc module sends packets to all local area neighbors. The abc
|
||||
* module adds no headers to outgoing packets.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section abc-channels Channels
|
||||
*
|
||||
* The abc module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -131,6 +131,7 @@ void announcement_remove(struct announcement *a);
|
|||
* \brief Set the value of an announcement
|
||||
* \param a A pointer to a struct announcement that has
|
||||
* previously been registered
|
||||
* \param value The new value
|
||||
*
|
||||
* This function sets the value of an announcement that
|
||||
* has previously been registered with
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
* announcement. THe module announces the announcements that have been
|
||||
* registered with the \ref rimeannouncement "announcement module".
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section bcast-announce-channels Channels
|
||||
*
|
||||
* The broadcast announcement module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
* either directly or indirectly through any of the other
|
||||
* communication primitives that are based on the broadcast primitive.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section broadcast-channels Channels
|
||||
*
|
||||
* The broadcast module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
* The collect module implements a hop-by-hop reliable data collection
|
||||
* mechanism.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section collect-channels Channels
|
||||
*
|
||||
* The collect module uses 2 channels; one for neighbor discovery and one
|
||||
* for data packets.
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
* The polite broadcast module does not add any packet attributes to
|
||||
* outgoing packets apart from those added by the upper layer.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section ipolite-channels Channels
|
||||
*
|
||||
* The ipolite module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
* receiver somewhere in the network.
|
||||
*
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section mesh-channels Channels
|
||||
*
|
||||
* The mesh module uses 3 channel; one for the multi-hop forwarding
|
||||
* (\ref rimemultihop "multihop") and two for the route disovery (\ref
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
* process.
|
||||
*
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section multihop-channels Channels
|
||||
*
|
||||
* The multihop module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
* discovery mechanism. A callback is invoked for every incoming
|
||||
* neighbor discovery message.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section neighbor-discovery-channels Channels
|
||||
*
|
||||
* The neighbor-discovery module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
* If the time to live reaches zero, the primitive does not forward
|
||||
* the packet.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section netflood-channels Channels
|
||||
*
|
||||
* The netflood module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -78,7 +78,7 @@ struct packetqueue {
|
|||
* This structure holds the state of a packet queue. It is
|
||||
* an opaque structure with no user-visible elements. The
|
||||
* function packetqueue_queuebuf() is used to extract a
|
||||
* \ref queuebuf "queubuf" from the item. The function
|
||||
* "queubuf" from the item. The function
|
||||
* packetqueue_ptr() is used to extract the opaque pointer
|
||||
* that was registered with the
|
||||
* packetqueue_enqueue_packetbuf() function.
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
* announcement. THe module announces the announcements that have been
|
||||
* registered with the \ref rimeannouncement "announcement module".
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section polite-announcement-channels Channels
|
||||
*
|
||||
* The polite announcement module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
* The polite broadcast module does not add any packet attributes to
|
||||
* outgoing packets apart from those added by the upper layer.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section polite-channels Channels
|
||||
*
|
||||
* The polite module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
* reliable single-hop primitive for the communication between two
|
||||
* single-hop neighbors.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section rmh-channels Channels
|
||||
*
|
||||
* The rmh module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
*
|
||||
* The route-discovery module does route discovery for Rime.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section route-discovery-channels Channels
|
||||
*
|
||||
* The ibc module uses 2 channels; one for the flooded route request
|
||||
* packets and one for the unicast route replies.
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
* The rudolph0 module implements a single-hop reliable bulk data
|
||||
* transfer mechanism.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section rudolph0-channels Channels
|
||||
*
|
||||
* The rudolph0 module uses 2 channels; one for data packets and one
|
||||
* for NACK and repair packets.
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
* The rudolph1 module implements a multi-hop reliable bulk data
|
||||
* transfer mechanism.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section rudolph1-channels Channels
|
||||
*
|
||||
* The rudolph1 module uses 2 channels; one for data transmissions and
|
||||
* one for NACKs and repair packets.
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
* The rudolph2 module implements a single-hop reliable bulk data
|
||||
* transfer mechanism.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section rudolph2-channels Channels
|
||||
*
|
||||
* The rudolph2 module uses 2 channels; one for data packets and one
|
||||
* for NACK and repair packets.
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
* callback.
|
||||
*
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section runicast-channels Channels
|
||||
*
|
||||
* The runicast module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
* either the message is canceled or a new message is sent. Messages
|
||||
* sent with the stbroadcast module are not identified with a sender ID.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section stbroadcast-channels Channels
|
||||
*
|
||||
* The stbroadcast module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
* number of retransmissions for a packet as a packet attribute on
|
||||
* outgoing packets.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section stunicast-channels Channels
|
||||
*
|
||||
* The stunicast module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
*
|
||||
* The trickle module sends a single packet to all nodes on the network.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section trickle-channels Channels
|
||||
*
|
||||
* The trickle module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
* single-hop receiver address attribute and discards the packet if
|
||||
* the address does not match the address of the node.
|
||||
*
|
||||
* \section channels Channels
|
||||
* \section unicast-channels Channels
|
||||
*
|
||||
* The unicast module uses 1 channel.
|
||||
*
|
||||
|
|
|
@ -195,4 +195,16 @@
|
|||
#define RPL_PREFERENCE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hop-by-hop option
|
||||
* This option control the insertion of the RPL Hop-by-Hop extension header
|
||||
* into packets originating from this node. Incoming Hop-by-hop extension
|
||||
* header are still processed and forwarded.
|
||||
*/
|
||||
#ifdef RPL_CONF_INSERT_HBH_OPTION
|
||||
#define RPL_INSERT_HBH_OPTION RPL_CONF_INSERT_HBH_OPTION
|
||||
#else
|
||||
#define RPL_INSERT_HBH_OPTION 1
|
||||
#endif
|
||||
|
||||
#endif /* RPL_CONF_H */
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "net/rpl/rpl-private.h"
|
||||
#include "net/ip/uip.h"
|
||||
#include "net/ipv6/uip-nd6.h"
|
||||
#include "net/ipv6/uip-ds6-nbr.h"
|
||||
#include "net/nbr-table.h"
|
||||
#include "net/ipv6/multicast/uip-mcast6.h"
|
||||
#include "lib/list.h"
|
||||
|
@ -79,6 +80,19 @@ NBR_TABLE(rpl_parent_t, rpl_parents);
|
|||
/* Allocate instance table. */
|
||||
rpl_instance_t instance_table[RPL_MAX_INSTANCES];
|
||||
rpl_instance_t *default_instance;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uip_ds6_nbr_t *
|
||||
rpl_get_nbr(rpl_parent_t *parent)
|
||||
{
|
||||
linkaddr_t *lladdr = NULL;
|
||||
lladdr = nbr_table_get_lladdr(rpl_parents, parent);
|
||||
if(lladdr != NULL) {
|
||||
return nbr_table_get_from_lladdr(ds6_neighbors, lladdr);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
nbr_callback(void *ptr)
|
||||
|
@ -113,9 +127,11 @@ rpl_get_parent_rank(uip_lladdr_t *addr)
|
|||
uint16_t
|
||||
rpl_get_parent_link_metric(const uip_lladdr_t *addr)
|
||||
{
|
||||
rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)addr);
|
||||
if(p != NULL) {
|
||||
return p->link_metric;
|
||||
uip_ds6_nbr_t *nbr;
|
||||
nbr = nbr_table_get_from_lladdr(ds6_neighbors, (const linkaddr_t *)addr);
|
||||
|
||||
if(nbr != NULL) {
|
||||
return nbr->link_metric;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -568,10 +584,17 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
|
|||
if(p == NULL) {
|
||||
PRINTF("RPL: rpl_add_parent p NULL\n");
|
||||
} else {
|
||||
uip_ds6_nbr_t *nbr;
|
||||
nbr = rpl_get_nbr(p);
|
||||
|
||||
p->dag = dag;
|
||||
p->rank = dio->rank;
|
||||
p->dtsn = dio->dtsn;
|
||||
p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
|
||||
|
||||
/* Check whether we have a neighbor that has not gotten a link metric yet */
|
||||
if(nbr != NULL && nbr->link_metric == 0) {
|
||||
nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
|
||||
}
|
||||
#if RPL_DAG_MC != RPL_DAG_MC_NONE
|
||||
memcpy(&p->mc, &dio->mc, sizeof(p->mc));
|
||||
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
||||
|
@ -766,7 +789,6 @@ rpl_nullify_parent(rpl_parent_t *parent)
|
|||
/* This function can be called when the preferred parent is NULL, so we
|
||||
need to handle this condition in order to trigger uip_ds6_defrt_rm. */
|
||||
if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
|
||||
rpl_set_preferred_parent(dag, NULL);
|
||||
dag->rank = INFINITE_RANK;
|
||||
if(dag->joined) {
|
||||
if(dag->instance->def_route != NULL) {
|
||||
|
@ -776,7 +798,11 @@ rpl_nullify_parent(rpl_parent_t *parent)
|
|||
uip_ds6_defrt_rm(dag->instance->def_route);
|
||||
dag->instance->def_route = NULL;
|
||||
}
|
||||
dao_output(parent, RPL_ZERO_LIFETIME);
|
||||
/* Send no-path DAO only to preferred parent, if any */
|
||||
if(parent == dag->preferred_parent) {
|
||||
dao_output(parent, RPL_ZERO_LIFETIME);
|
||||
rpl_set_preferred_parent(dag, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -949,6 +975,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
}
|
||||
}
|
||||
|
||||
#if RPL_MAX_DAG_PER_INSTANCE > 1
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||
|
@ -1028,6 +1055,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
rpl_process_parent_event(instance, p);
|
||||
p->dtsn = dio->dtsn;
|
||||
}
|
||||
#endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
@ -1037,6 +1065,14 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
|
|||
|
||||
remove_parents(dag, 0);
|
||||
dag->version = dio->version;
|
||||
|
||||
/* copy parts of the configuration so that it propagates in the network */
|
||||
dag->instance->dio_intdoubl = dio->dag_intdoubl;
|
||||
dag->instance->dio_intmin = dio->dag_intmin;
|
||||
dag->instance->dio_redundancy = dio->dag_redund;
|
||||
dag->instance->default_lifetime = dio->default_lifetime;
|
||||
dag->instance->lifetime_unit = dio->lifetime_unit;
|
||||
|
||||
dag->instance->of->reset(dag);
|
||||
dag->min_rank = INFINITE_RANK;
|
||||
RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out);
|
||||
|
@ -1215,9 +1251,14 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
}
|
||||
|
||||
if(dag == NULL) {
|
||||
#if RPL_MAX_DAG_PER_INSTANCE > 1
|
||||
PRINTF("RPL: Adding new DAG to known instance.\n");
|
||||
rpl_add_dag(from, dio);
|
||||
return;
|
||||
#else /* RPL_MAX_DAG_PER_INSTANCE > 1 */
|
||||
PRINTF("RPL: Only one instance supported.\n");
|
||||
return;
|
||||
#endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -215,6 +215,7 @@ rpl_update_header_empty(void)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
#if RPL_INSERT_HBH_OPTION
|
||||
PRINTF("RPL: No hop-by-hop option found, creating it\n");
|
||||
if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) {
|
||||
PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n");
|
||||
|
@ -223,6 +224,7 @@ rpl_update_header_empty(void)
|
|||
}
|
||||
set_rpl_opt(uip_ext_opt_offset);
|
||||
uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -374,9 +376,11 @@ rpl_invert_header(void)
|
|||
void
|
||||
rpl_insert_header(void)
|
||||
{
|
||||
#if RPL_INSERT_HBH_OPTION
|
||||
if(default_instance != NULL && !uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
||||
rpl_update_header_empty();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
/*---------------------------------------------------------------------------*/
|
||||
#define RPL_DIO_GROUNDED 0x80
|
||||
#define RPL_DIO_MOP_SHIFT 3
|
||||
#define RPL_DIO_MOP_MASK 0x3c
|
||||
#define RPL_DIO_MOP_MASK 0x38
|
||||
#define RPL_DIO_PREFERENCE_MASK 0x07
|
||||
|
||||
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
@ -778,6 +778,7 @@ dao_input(void)
|
|||
|
||||
rep->state.lifetime = RPL_LIFETIME(instance, lifetime);
|
||||
rep->state.learned_from = learned_from;
|
||||
rep->state.nopath_received = 0;
|
||||
|
||||
#if RPL_CONF_MULTICAST
|
||||
fwd_dao:
|
||||
|
|
|
@ -90,16 +90,22 @@ typedef uint16_t rpl_path_metric_t;
|
|||
static rpl_path_metric_t
|
||||
calculate_path_metric(rpl_parent_t *p)
|
||||
{
|
||||
uip_ds6_nbr_t *nbr;
|
||||
if(p == NULL) {
|
||||
return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
|
||||
}
|
||||
|
||||
nbr = rpl_get_nbr(p);
|
||||
if(nbr == NULL) {
|
||||
return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
|
||||
}
|
||||
#if RPL_DAG_MC == RPL_DAG_MC_NONE
|
||||
return p->rank + (uint16_t)p->link_metric;
|
||||
{
|
||||
return p->rank + (uint16_t)nbr->link_metric;
|
||||
}
|
||||
#elif RPL_DAG_MC == RPL_DAG_MC_ETX
|
||||
return p->mc.obj.etx + (uint16_t)p->link_metric;
|
||||
return p->mc.obj.etx + (uint16_t)nbr->link_metric;
|
||||
#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
|
||||
return p->mc.obj.energy.energy_est + (uint16_t)p->link_metric;
|
||||
return p->mc.obj.energy.energy_est + (uint16_t)nbr->link_metric;
|
||||
#else
|
||||
#error "Unsupported RPL_DAG_MC configured. See rpl.h."
|
||||
#endif /* RPL_DAG_MC */
|
||||
|
@ -114,9 +120,18 @@ reset(rpl_dag_t *dag)
|
|||
static void
|
||||
neighbor_link_callback(rpl_parent_t *p, int status, int numtx)
|
||||
{
|
||||
uint16_t recorded_etx = p->link_metric;
|
||||
uint16_t recorded_etx = 0;
|
||||
uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR;
|
||||
uint16_t new_etx;
|
||||
uip_ds6_nbr_t *nbr = NULL;
|
||||
|
||||
nbr = rpl_get_nbr(p);
|
||||
if(nbr == NULL) {
|
||||
/* No neighbor for this parent - something bad has occurred */
|
||||
return;
|
||||
}
|
||||
|
||||
recorded_etx = nbr->link_metric;
|
||||
|
||||
/* Do not penalize the ETX when collisions or transmission errors occur. */
|
||||
if(status == MAC_TX_OK || status == MAC_TX_NOACK) {
|
||||
|
@ -139,7 +154,8 @@ neighbor_link_callback(rpl_parent_t *p, int status, int numtx)
|
|||
(unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR),
|
||||
(unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR),
|
||||
(unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR));
|
||||
p->link_metric = new_etx;
|
||||
/* update the link metric for this nbr */
|
||||
nbr->link_metric = new_etx;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,14 +164,15 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
|
|||
{
|
||||
rpl_rank_t new_rank;
|
||||
rpl_rank_t rank_increase;
|
||||
uip_ds6_nbr_t *nbr;
|
||||
|
||||
if(p == NULL) {
|
||||
if(p == NULL || (nbr = rpl_get_nbr(p)) == NULL) {
|
||||
if(base_rank == 0) {
|
||||
return INFINITE_RANK;
|
||||
}
|
||||
rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
|
||||
} else {
|
||||
rank_increase = p->link_metric;
|
||||
rank_increase = nbr->link_metric;
|
||||
if(base_rank == 0) {
|
||||
base_rank = p->rank;
|
||||
}
|
||||
|
|
|
@ -126,26 +126,34 @@ static rpl_parent_t *
|
|||
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
|
||||
{
|
||||
rpl_rank_t r1, r2;
|
||||
rpl_dag_t *dag;
|
||||
rpl_dag_t *dag;
|
||||
uip_ds6_nbr_t *nbr1, *nbr2;
|
||||
nbr1 = rpl_get_nbr(p1);
|
||||
nbr2 = rpl_get_nbr(p2);
|
||||
|
||||
dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */
|
||||
|
||||
if(nbr1 == NULL || nbr2 == NULL) {
|
||||
return dag->preferred_parent;
|
||||
}
|
||||
|
||||
PRINTF("RPL: Comparing parent ");
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(p1));
|
||||
PRINTF(" (confidence %d, rank %d) with parent ",
|
||||
p1->link_metric, p1->rank);
|
||||
nbr1->link_metric, p1->rank);
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(p2));
|
||||
PRINTF(" (confidence %d, rank %d)\n",
|
||||
p2->link_metric, p2->rank);
|
||||
nbr2->link_metric, p2->rank);
|
||||
|
||||
|
||||
r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC +
|
||||
p1->link_metric;
|
||||
nbr1->link_metric;
|
||||
r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC +
|
||||
p2->link_metric;
|
||||
nbr2->link_metric;
|
||||
/* Compare two parents by looking both and their rank and at the ETX
|
||||
for that parent. We choose the parent that has the most
|
||||
favourable combination. */
|
||||
|
||||
dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */
|
||||
if(r1 < r2 + MIN_DIFFERENCE &&
|
||||
r1 > r2 - MIN_DIFFERENCE) {
|
||||
return dag->preferred_parent;
|
||||
|
|
|
@ -145,7 +145,7 @@ handle_dio_timer(void *ptr)
|
|||
|
||||
if(instance->dio_send) {
|
||||
/* send DIO if counter is less than desired redundancy */
|
||||
if(instance->dio_counter < instance->dio_redundancy) {
|
||||
if(instance->dio_redundancy != 0 && instance->dio_counter < instance->dio_redundancy) {
|
||||
#if RPL_CONF_STATS
|
||||
instance->dio_totsend++;
|
||||
#endif /* RPL_CONF_STATS */
|
||||
|
|
|
@ -76,9 +76,9 @@ rpl_set_mode(enum rpl_mode m)
|
|||
switching to. */
|
||||
if(m == RPL_MODE_MESH) {
|
||||
|
||||
/* If we switcht to mesh mode, we should send out a DAO message to
|
||||
/* If we switch to mesh mode, we should send out a DAO message to
|
||||
inform our parent that we now are reachable. Before we do this,
|
||||
we must set the mode variable, since DAOs will not be send if
|
||||
we must set the mode variable, since DAOs will not be sent if
|
||||
we are in feather mode. */
|
||||
PRINTF("RPL: switching to mesh mode\n");
|
||||
mode = m;
|
||||
|
|
|
@ -114,7 +114,6 @@ struct rpl_parent {
|
|||
rpl_metric_container_t mc;
|
||||
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
||||
rpl_rank_t rank;
|
||||
uint16_t link_metric;
|
||||
uint8_t dtsn;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
@ -251,7 +250,7 @@ rpl_parent_t *rpl_get_parent(uip_lladdr_t *addr);
|
|||
rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr);
|
||||
uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr);
|
||||
void rpl_dag_init(void);
|
||||
|
||||
uip_ds6_nbr_t *rpl_get_nbr(rpl_parent_t *parent);
|
||||
|
||||
/**
|
||||
* RPL modes
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
* strings.
|
||||
*
|
||||
* We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow
|
||||
* concatenation of two #defined macros.
|
||||
* concatenation of two \#defined macros.
|
||||
*/
|
||||
#define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2)
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
*
|
||||
* \note The clock library need in many cases not be used
|
||||
* directly. Rather, the \ref timer "timer library", \ref etimer
|
||||
* "event timers", or \ref trimer "rtimer library" should be used.
|
||||
* "event timers", or \ref rtimer "rtimer library" should be used.
|
||||
*
|
||||
* \sa \ref timer "Timer library"
|
||||
* \sa \ref etimer "Event timers"
|
||||
|
|
|
@ -105,7 +105,7 @@ struct dsc {
|
|||
*
|
||||
* \param prgname The name of the program on disk.
|
||||
*
|
||||
* \param initfunc A pointer to the initialization function of the
|
||||
* \param process A pointer to the initialization function of the
|
||||
* program.
|
||||
*
|
||||
* \param icon A pointer to the CTK icon.
|
||||
|
|
|
@ -267,7 +267,7 @@ do_event(void)
|
|||
receiver = events[fevent].p;
|
||||
|
||||
/* Since we have seen the new event, we move pointer upwards
|
||||
and decrese the number of events. */
|
||||
and decrease the number of events. */
|
||||
fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS;
|
||||
--nevents;
|
||||
|
||||
|
@ -337,7 +337,7 @@ process_post(struct process *p, process_event_t ev, process_data_t data)
|
|||
if(p == PROCESS_BROADCAST) {
|
||||
printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current));
|
||||
} else {
|
||||
printf("soft panic: event queue is full when event %d was posted to %s frpm %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current));
|
||||
printf("soft panic: event queue is full when event %d was posted to %s from %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
return PROCESS_ERR_FULL;
|
||||
|
|
|
@ -335,7 +335,7 @@ struct process {
|
|||
*
|
||||
* \param p A pointer to a process structure.
|
||||
*
|
||||
* \param arg An argument pointer that can be passed to the new
|
||||
* \param data An argument pointer that can be passed to the new
|
||||
* process
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -76,8 +76,9 @@ timer_set(struct timer *t, clock_time_t interval)
|
|||
* function will cause the timer to be stable over time, unlike the
|
||||
* timer_restart() function.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
* \note Must not be executed before timer expired
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
* \sa timer_restart()
|
||||
*/
|
||||
void
|
||||
|
|
|
@ -117,7 +117,7 @@ makestrings(void)
|
|||
makeaddr(&addr, gateway);
|
||||
|
||||
#if WITH_DNS
|
||||
addrptr = resolv_getserver();
|
||||
addrptr = uip_nameserver_get(0);
|
||||
if(addrptr != NULL) {
|
||||
makeaddr(addrptr, dnsserver);
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ dhcpc_configured(const struct dhcpc_state *s)
|
|||
uip_setnetmask(&s->netmask);
|
||||
uip_setdraddr(&s->default_router);
|
||||
#if WITH_DNS
|
||||
resolv_conf(&s->dnsaddr);
|
||||
uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME);
|
||||
#endif /* WITH_DNS */
|
||||
|
||||
set_statustext("Configured.");
|
||||
|
@ -261,7 +261,7 @@ dhcpc_unconfigured(const struct dhcpc_state *s)
|
|||
uip_setnetmask(&nulladdr);
|
||||
uip_setdraddr(&nulladdr);
|
||||
#if WITH_DNS
|
||||
resolv_conf(&nulladdr);
|
||||
uip_nameserver_update(&nulladdr, UIP_NAMESERVER_INFINITE_LIFETIME);
|
||||
#endif /* WITH_DNS */
|
||||
|
||||
set_statustext("Unconfigured.");
|
||||
|
|
|
@ -105,7 +105,7 @@ config_read(char *filename)
|
|||
uip_setnetmask(&config.netmask);
|
||||
uip_setdraddr(&config.draddr);
|
||||
#if WITH_DNS
|
||||
resolv_conf(&config.resolvaddr);
|
||||
uip_nameserver_update(&config.resolvaddr, UIP_NAMESERVER_INFINITE_LIFETIME);
|
||||
#endif /* WITH_DNS */
|
||||
|
||||
return &config.ethernetcfg;
|
||||
|
|
|
@ -39,8 +39,8 @@ CROSS_COMPILE = arm-none-eabi-
|
|||
CC = $(CROSS_COMPILE)gcc
|
||||
LD = $(CROSS_COMPILE)gcc
|
||||
AS = $(CROSS_COMPILE)gcc
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
NM = $(CROSS_COMPILE)nm
|
||||
AR = $(CROSS_COMPILE)gcc-ar
|
||||
NM = $(CROSS_COMPILE)gcc-nm
|
||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||
STRIP = $(CROSS_COMPILE)strip
|
||||
|
|
|
@ -159,7 +159,7 @@ clock_set_seconds(unsigned long sec)
|
|||
seconds = sec;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
/*
|
||||
* Wait for a number of clock ticks.
|
||||
*/
|
||||
void
|
||||
|
@ -175,7 +175,7 @@ clock_wait(clock_time_t t)
|
|||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
/*
|
||||
* Delay the CPU for up to 65535*(4000000/F_CPU) microseconds.
|
||||
* Copied from _delay_loop_2 in AVR library delay_basic.h, 4 clocks per loop.
|
||||
* For accurate short delays, inline _delay_loop_2 in the caller, use a constant
|
||||
|
@ -193,44 +193,44 @@ my_delay_loop_2(uint16_t __count)
|
|||
);
|
||||
}
|
||||
void
|
||||
clock_delay_usec(uint16_t howlong)
|
||||
clock_delay_usec(uint16_t dt)
|
||||
{
|
||||
#if 0
|
||||
/* Accurate delay at any frequency, but introduces a 64 bit intermediate
|
||||
* and has a 279 clock overhead.
|
||||
*/
|
||||
if(howlong<=(uint16_t)(279000000UL/F_CPU)) return;
|
||||
howlong-=(uint16_t) (279000000UL/F_CPU);
|
||||
my_delay_loop_2(((uint64_t)(howlong) * (uint64_t) F_CPU) / 4000000ULL);
|
||||
if(dt<=(uint16_t)(279000000UL/F_CPU)) return;
|
||||
dt-=(uint16_t) (279000000UL/F_CPU);
|
||||
my_delay_loop_2(((uint64_t)(dt) * (uint64_t) F_CPU) / 4000000ULL);
|
||||
/* Remaining numbers tweaked for the breakpoint CPU frequencies */
|
||||
/* Add other frequencies as necessary */
|
||||
#elif F_CPU>=16000000UL
|
||||
if(howlong<1) return;
|
||||
my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000)));
|
||||
if(dt<1) return;
|
||||
my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000)));
|
||||
#elif F_CPU >= 12000000UL
|
||||
if(howlong<2) return;
|
||||
howlong-=(uint16_t) (3*12000000/F_CPU);
|
||||
my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000)));
|
||||
if(dt<2) return;
|
||||
dt-=(uint16_t) (3*12000000/F_CPU);
|
||||
my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000)));
|
||||
#elif F_CPU >= 8000000UL
|
||||
if(howlong<4) return;
|
||||
howlong-=(uint16_t) (3*8000000/F_CPU);
|
||||
my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2);
|
||||
if(dt<4) return;
|
||||
dt-=(uint16_t) (3*8000000/F_CPU);
|
||||
my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2);
|
||||
#elif F_CPU >= 4000000UL
|
||||
if(howlong<5) return;
|
||||
howlong-=(uint16_t) (4*4000000/F_CPU);
|
||||
my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2);
|
||||
if(dt<5) return;
|
||||
dt-=(uint16_t) (4*4000000/F_CPU);
|
||||
my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2);
|
||||
#elif F_CPU >= 2000000UL
|
||||
if(howlong<11) return;
|
||||
howlong-=(uint16_t) (10*2000000/F_CPU);
|
||||
my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4);
|
||||
if(dt<11) return;
|
||||
dt-=(uint16_t) (10*2000000/F_CPU);
|
||||
my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4);
|
||||
#elif F_CPU >= 1000000UL
|
||||
if(howlong<=17) return;
|
||||
howlong-=(uint16_t) (17*1000000/F_CPU);
|
||||
my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4);
|
||||
if(dt<=17) return;
|
||||
dt-=(uint16_t) (17*1000000/F_CPU);
|
||||
my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4);
|
||||
#else
|
||||
howlong >> 5;
|
||||
if (howlong < 1) return;
|
||||
my_delay_loop_2(howlong);
|
||||
dt >> 5;
|
||||
if (dt < 1) return;
|
||||
my_delay_loop_2(dt);
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
|
@ -250,7 +250,7 @@ clock_delay(unsigned int howlong)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Delay up to 65535 milliseconds.
|
||||
* \param dt How many milliseconds to delay.
|
||||
* \param howlong How many milliseconds to delay.
|
||||
*
|
||||
* Neither interrupts nor the watchdog timer is disabled over the delay.
|
||||
* Platforms are not required to implement this call.
|
||||
|
@ -279,7 +279,7 @@ clock_delay_msec(uint16_t howlong)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Adjust the system current clock time.
|
||||
* \param dt How many ticks to add
|
||||
* \param howmany How many ticks to add
|
||||
*
|
||||
* Typically used to add ticks after an MCU sleep
|
||||
* clock_seconds will increment if necessary to reflect the tick addition.
|
||||
|
|
|
@ -49,8 +49,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef RADIO_H
|
||||
#define RADIO_H
|
||||
#ifndef RF230BB_H_
|
||||
#define RF230BB_H_
|
||||
/*============================ INCLUDE =======================================*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -225,6 +225,6 @@ uint8_t rf230_get_raw_rssi(void);
|
|||
|
||||
#define rf230_rssi rf230_get_raw_rssi
|
||||
|
||||
#endif
|
||||
#endif /* RF230BB_H_ */
|
||||
/** @} */
|
||||
/*EOF*/
|
||||
|
|
|
@ -54,7 +54,7 @@ static unsigned long timer_value;
|
|||
static volatile CC_AT_DATA clock_time_t count = 0; /* Uptime in ticks */
|
||||
static volatile CC_AT_DATA clock_time_t seconds = 0; /* Uptime in secs */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
/*
|
||||
* Each iteration is ~1.0xy usec, so this function delays for roughly len usec
|
||||
*/
|
||||
void
|
||||
|
@ -68,7 +68,7 @@ clock_delay_usec(uint16_t len)
|
|||
ENABLE_INTERRUPTS();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
/*
|
||||
* Wait for a multiple of ~8 ms (a tick)
|
||||
*/
|
||||
void
|
||||
|
|
|
@ -52,6 +52,7 @@ CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
|
|||
CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c
|
||||
CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c
|
||||
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c
|
||||
CONTIKI_CPU_SOURCEFILES += i2c.c
|
||||
|
||||
DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c
|
||||
|
||||
|
|
|
@ -96,17 +96,17 @@ clock_init(void)
|
|||
REG(SYS_CTRL_RCGCGPT) |= SYS_CTRL_RCGCGPT_GPT0;
|
||||
|
||||
/* Make sure GPT0 is off */
|
||||
REG(GPT_0_BASE | GPTIMER_CTL) = 0;
|
||||
REG(GPT_0_BASE + GPTIMER_CTL) = 0;
|
||||
|
||||
|
||||
/* 16-bit */
|
||||
REG(GPT_0_BASE | GPTIMER_CFG) = 0x04;
|
||||
REG(GPT_0_BASE + GPTIMER_CFG) = 0x04;
|
||||
|
||||
/* One-Shot, Count Down, No Interrupts */
|
||||
REG(GPT_0_BASE | GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT;
|
||||
REG(GPT_0_BASE + GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT;
|
||||
|
||||
/* Prescale by 16 (thus, value 15 in TAPR) */
|
||||
REG(GPT_0_BASE | GPTIMER_TAPR) = 0x0F;
|
||||
REG(GPT_0_BASE + GPTIMER_TAPR) = 0x0F;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
CCIF clock_time_t
|
||||
|
@ -136,20 +136,19 @@ clock_wait(clock_time_t i)
|
|||
while(clock_time() - start < (clock_time_t)i);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Arch-specific implementation of clock_delay_usec for the cc2538
|
||||
* \param len Delay \e len uSecs
|
||||
/*
|
||||
* Arch-specific implementation of clock_delay_usec for the cc2538
|
||||
*
|
||||
* See clock_init() for GPT0 Timer A's configuration
|
||||
*/
|
||||
void
|
||||
clock_delay_usec(uint16_t len)
|
||||
clock_delay_usec(uint16_t dt)
|
||||
{
|
||||
REG(GPT_0_BASE | GPTIMER_TAILR) = len;
|
||||
REG(GPT_0_BASE | GPTIMER_CTL) |= GPTIMER_CTL_TAEN;
|
||||
REG(GPT_0_BASE + GPTIMER_TAILR) = dt;
|
||||
REG(GPT_0_BASE + GPTIMER_CTL) |= GPTIMER_CTL_TAEN;
|
||||
|
||||
/* One-Shot mode: TAEN will be cleared when the timer reaches 0 */
|
||||
while(REG(GPT_0_BASE | GPTIMER_CTL) & GPTIMER_CTL_TAEN);
|
||||
while(REG(GPT_0_BASE + GPTIMER_CTL) & GPTIMER_CTL_TAEN);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
|
|
|
@ -29,12 +29,21 @@
|
|||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \addtogroup cc2538
|
||||
* \addtogroup platform
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc2538-platforms TI cc2538-powered platforms
|
||||
*
|
||||
* Documentation for all platforms powered by the TI cc2538 System-on-Chip
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc2538 The TI cc2538 System-on-Chip
|
||||
* CPU-Specific functionality - available to all cc2538-based platforms
|
||||
* @{
|
||||
*
|
||||
* \defgroup cc2538-cpu cc2538 CPU
|
||||
*
|
||||
* cc2538 CPU-specific functions for the cc2538 core
|
||||
* CPU-specific functions for the cc2538 core
|
||||
* @{
|
||||
*
|
||||
* \file
|
||||
|
@ -60,6 +69,8 @@ unsigned long cpu_cpsie(void);
|
|||
#endif /* CPU_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue