Contiki 3.x
res_routes.c
Go to the documentation of this file.
1 /**
2  * @file
3  * Route resource.
4  * Displays the neighbour and route tables of the node.
5  * Arthur Fabre
6  */
7 
8 #include "er-server.h"
9 #include "rest-engine.h"
10 #include <inttypes.h>
11 #include <stdlib.h>
12 #include <stdbool.h>
13 #include <string.h>
14 #include "net/ip/uip.h"
15 #include "net/ipv6/uip-ds6.h"
16 #include "net/rpl/rpl.h"
17 
18 #define DEBUG_ON
19 #include "debug.h"
20 
21 /**
22  * Maximum length of an single nbr / route entry,
23  * including terminating null byte
24  */
25 #define MAX_ENTRY_SIZE 12
26 
27 /**
28  * The next route to use.
29  * Can be null.
30  */
32 
33 /**
34  * The next neighbour to use.
35  * Can be null.
36  */
38 
39 /**
40  * True if all the neighbors have been sent, and we should start sending routes.
41  */
42 static bool hasReachedRoutes;
43 
44 /**
45  * Get last 2 bytes of an IP as a uint16_t that can be hex printed.
46  */
47 static uint16_t get_hex_ip(uip_ipaddr_t *ip);
48 
49 /**
50  * Reset our internal state so that subsequent calls to get_next_nbr / route return the first ones.
51  */
52 static void reset_nbr_route();
53 
54 /**
55  * Get the next neighbour if there is one, otherwise the next route. Set hasReachedRoutes accordingly.
56  * @return true if something was received, false otherwise.
57  */
58 static bool get_next_nbr_route();
59 
60 /**
61  * Get the next neighbour if there is one.
62  * @return true if something was received, false otherwise.
63  */
64 static bool get_next_nbr();
65 
66 /**
67  * Get the next route if there is one.
68  * @return true if something was received, false otherwise.
69  */
70 static bool get_next_route();
71 
72 /**
73  * Get handler for this resource
74  */
75 static void res_get_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
76 
77 /**
78  * Route resource.
79  */
80 RESOURCE(res_routes, "Routes", res_get_handler, NULL, NULL, NULL);
81 
82 void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) {
83  int buffer_len = 0;
84 
85  DEBUG("Serving routes req Offset %d, PrefSize %d\n", (int) *offset, preferred_size);
86 
87  // If this is the first request get the first ip address
88  if (*offset == 0) {
90  DEBUG("First request, resetting neighbour and route\n");
91  if (!get_next_nbr_route()) {
92  // No routes at all, end of request.
93  char *error = "No nbrs / routes\n";
94  DEBUG("%s", error);
95  memcpy(buffer, error, strlen(error));
96  REST.set_response_payload(response, buffer, strlen(error));
97  // offset -1 means it is the end of a block req
98  *offset = -1;
99  return;
100  }
101 
102  DEBUG("Printing preferred parent\n");
103 
104  rpl_dag_t *dag = rpl_get_any_dag();
105 
106  buffer_len += snprintf((char *) buffer, preferred_size, "%04x\n\n", get_hex_ip(rpl_get_parent_ipaddr(dag->preferred_parent)));
107  }
108 
109  // Assume we have things left to send until we don't
110  *offset += preferred_size;
111 
112  // Keep going until we don't have enough room to fit an entry in
113  while (preferred_size - buffer_len > MAX_ENTRY_SIZE) {
114 
115  // Write a maximum of MAX_ENTRY_SIZE, as we know we have at least that much buffer space avail at this point.
116  if (!hasReachedRoutes) {
117  DEBUG("Printing nbr\n");
118  buffer_len += snprintf((char *) buffer + buffer_len, MAX_ENTRY_SIZE, "%04x\n", get_hex_ip(&(nbr->ipaddr)));
119  } else {
120  DEBUG("Printing route\n");
121  buffer_len += snprintf((char *) buffer + buffer_len, MAX_ENTRY_SIZE, "%04x@%04x\n", get_hex_ip(&(route->ipaddr)), get_hex_ip(uip_ds6_route_nexthop(route)));
122  }
123 
124  // Get the next thing
125  if (!get_next_nbr_route()) {
126  // No next route, end of request.
127  DEBUG("No more routes\n");
128  *offset = -1;
129  break;
130  }
131  }
132 
133  REST.set_response_payload(response, buffer, buffer_len);
134 }
135 
136 inline uint16_t get_hex_ip(uip_ipaddr_t *ipaddr) {
137  return (ipaddr->u8[14] << 8) + ipaddr->u8[15];
138 }
139 
140 inline void reset_nbr_route() {
141  route = NULL;
142  nbr = NULL;
143  hasReachedRoutes = false;
144 }
145 
146 inline bool get_next_nbr_route() {
147  // If we haven't reached the end of the neighbours, and there is still one more neighbour, get that.
149  return true;
150  }
151 
152  // Otherwise attempt to get a route
153  return get_next_route();
154 }
155 
156 inline bool get_next_nbr() {
157  if (nbr == NULL) {
158  nbr = nbr_table_head(ds6_neighbors);
159  } else {
160  nbr = nbr_table_next(ds6_neighbors, nbr);
161  }
162 
163  DEBUG("Got nbr %p\n", nbr);
164  return nbr != NULL;
165 }
166 
167 inline bool get_next_route() {
168  if (route == NULL) {
169  route = uip_ds6_route_head();
170  } else {
171  route = uip_ds6_route_next(route);
172  }
173 
174  DEBUG("Got route %p\n", route);
175  return route != NULL;
176 }
static bool get_next_nbr_route()
Get the next neighbour if there is one, otherwise the next route.
Definition: res_routes.c:146
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:129
Header file for IPv6-related data structures.
An abstraction layer for RESTful Web services (Erbium).
static uint16_t get_hex_ip(uip_ipaddr_t *ip)
Get last 2 bytes of an IP as a uint16_t that can be hex printed.
Definition: res_routes.c:136
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:70
static uip_ds6_route_t * route
The next route to use.
Definition: res_routes.c:31
#define NULL
The null pointer.
static uip_ds6_nbr_t * nbr
The next neighbour to use.
Definition: res_routes.c:37
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
Get handler for this resource.
Definition: res_routes.c:82
static bool get_next_nbr()
Get the next neighbour if there is one.
Definition: res_routes.c:156
Header file for the uIP TCP/IP stack.
RESOURCE(res_routes,"Routes", res_get_handler, NULL, NULL, NULL)
Route resource.
static void reset_nbr_route()
Reset our internal state so that subsequent calls to get_next_nbr / route return the first ones...
Definition: res_routes.c:140
static bool get_next_route()
Get the next route if there is one.
Definition: res_routes.c:167
static bool hasReachedRoutes
True if all the neighbors have been sent, and we should start sending routes.
Definition: res_routes.c:42
An entry in the routing table.
#define MAX_ENTRY_SIZE
Maximum length of an single nbr / route entry, including terminating null byte.
Definition: res_routes.c:25