Contiki 3.x
rest-engine.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \file
34  * An abstraction layer for RESTful Web services (Erbium).
35  * Inspired by RESTful Contiki by Dogan Yazar.
36  * \author
37  * Matthias Kovatsch <kovatsch@inf.ethz.ch>
38  */
39 
40 #ifndef REST_ENGINE_H_
41 #define REST_ENGINE_H_
42 
43 #include <stdio.h>
44 #include "contiki.h"
45 #include "contiki-lib.h"
46 #include "rest-constants.h"
47 
48 /* list of valid REST Enigne implementations */
49 #define REGISTERED_ENGINE_ERBIUM coap_rest_implementation
50 #define REGISTERED_ENGINE_HELIUM http_rest_implementation
51 
52 /* sanity check for configured implementation */
53 #if !defined(REST) || (REST != REGISTERED_ENGINE_ERBIUM && REST != REGISTERED_ENGINE_HELIUM)
54 #error "Define a valid REST Engine implementation (REST define)!"
55 #endif
56 
57 /*
58  * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer.
59  * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks.
60  */
61 #ifndef REST_MAX_CHUNK_SIZE
62 #define REST_MAX_CHUNK_SIZE 64
63 #endif
64 
65 struct resource_s;
66 struct periodic_resource_s;
67 
68 /* signatures of handler functions */
69 typedef void (*restful_handler)(void *request, void *response,
70  uint8_t *buffer, uint16_t preferred_size,
71  int32_t *offset);
72 typedef void (*restful_final_handler)(struct resource_s *resource,
73  void *request, void *response);
74 typedef void (*restful_periodic_handler)(void);
75 typedef void (*restful_response_handler)(void *data, void *response);
76 typedef void (*restful_trigger_handler)(void);
77 
78 /* signature of the rest-engine service function */
79 typedef int (*service_callback_t)(void *request, void *response,
80  uint8_t *buffer, uint16_t preferred_size,
81  int32_t *offset);
82 
83 /* data structure representing a resource in REST */
84 struct resource_s {
85  struct resource_s *next; /* for LIST, points to next resource defined */
86  const char *url; /*handled URL */
87  rest_resource_flags_t flags; /* handled RESTful methods */
88  const char *attributes; /* link-format attributes */
89  restful_handler get_handler; /* handler function */
90  restful_handler post_handler; /* handler function */
91  restful_handler put_handler; /* handler function */
92  restful_handler delete_handler; /* handler function */
93  union {
94  struct periodic_resource_s *periodic; /* special data depending on flags */
95  restful_trigger_handler trigger;
96  restful_trigger_handler resume;
97  };
98 };
99 typedef struct resource_s resource_t;
100 
101 struct periodic_resource_s {
102  struct periodic_resource_s *next; /* for LIST, points to next resource defined */
103  const resource_t *resource;
104  uint32_t period;
105  struct etimer periodic_timer;
106  const restful_periodic_handler periodic_handler;
107 };
108 typedef struct periodic_resource_s periodic_resource_t;
109 
110 /*
111  * Macro to define a RESTful resource.
112  * Resources are statically defined for the sake of efficiency and better memory management.
113  */
114 #define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \
115  resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } }
116 
117 #define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \
118  resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } }
119 
120 #define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \
121  resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } }
122 
123 #define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \
124  resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } }
125 
126 /*
127  * Macro to define a periodic resource.
128  * The corresponding [name]_periodic_handler() function will be called every period.
129  * For instance polling a sensor and publishing a changed value to subscribed clients would be done there.
130  * The subscriber list will be maintained by the final_handler rest_subscription_handler() (see rest-mapping header file).
131  */
132 #define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \
133  periodic_resource_t periodic_##name; \
134  resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } }; \
135  periodic_resource_t periodic_##name = { NULL, &name, period, { { 0 } }, periodic_handler };
136 
137 struct rest_implementation {
138  char *name;
139 
140  /** Initialize the REST implementation. */
141  void (*init)(void);
142 
143  /** Register the RESTful service callback at implementation. */
144  void (*set_service_callback)(service_callback_t callback);
145 
146  /** Get request URI path. */
147  int (*get_url)(void *request, const char **url);
148 
149  /** Get the method of a request. */
150  rest_resource_flags_t (*get_method_type)(void *request);
151 
152  /** Set the status code of a response. */
153  int (*set_response_status)(void *response, unsigned int code);
154 
155  /** Get the content-type of a request. */
156  int (*get_header_content_type)(void *request,
157  unsigned int *content_format);
158 
159  /** Set the Content-Type of a response. */
160  int (*set_header_content_type)(void *response,
161  unsigned int content_format);
162 
163  /** Get the Accept types of a request. */
164  int (*get_header_accept)(void *request, unsigned int *accept);
165 
166  /** Get the Length option of a request. */
167  int (*get_header_length)(void *request, uint32_t *size);
168 
169  /** Set the Length option of a response. */
170  int (*set_header_length)(void *response, uint32_t size);
171 
172  /** Get the Max-Age option of a request. */
173  int (*get_header_max_age)(void *request, uint32_t *age);
174 
175  /** Set the Max-Age option of a response. */
176  int (*set_header_max_age)(void *response, uint32_t age);
177 
178  /** Set the ETag option of a response. */
179  int (*set_header_etag)(void *response, const uint8_t *etag,
180  size_t length);
181 
182  /** Get the If-Match option of a request. */
183  int (*get_header_if_match)(void *request, const uint8_t **etag);
184 
185  /** Get the If-Match option of a request. */
186  int (*get_header_if_none_match)(void *request);
187 
188  /** Get the Host option of a request. */
189  int (*get_header_host)(void *request, const char **host);
190 
191  /** Set the location option of a response. */
192  int (*set_header_location)(void *response, const char *location);
193 
194  /** Get the payload option of a request. */
195  int (*get_request_payload)(void *request, const uint8_t **payload);
196 
197  /** Set the payload option of a response. */
198  int (*set_response_payload)(void *response, const void *payload,
199  size_t length);
200 
201  /** Get the query string of a request. */
202  int (*get_query)(void *request, const char **value);
203 
204  /** Get the value of a request query key-value pair. */
205  int (*get_query_variable)(void *request, const char *name,
206  const char **value);
207 
208  /** Get the value of a request POST key-value pair. */
209  int (*get_post_variable)(void *request, const char *name,
210  const char **value);
211 
212  /** Send the payload to all subscribers of the resource at url. */
213  void (*notify_subscribers)(resource_t *resource);
214 
215  /** The handler for resource subscriptions. */
216  restful_final_handler subscription_handler;
217 
218  /* REST status codes. */
219  const struct rest_implementation_status status;
220 
221  /* REST content-types. */
222  const struct rest_implementation_type type;
223 };
224 
225 /* instance of REST implementation */
226 extern const struct rest_implementation REST;
227 
228 /*
229  * To be called by HTTP/COAP server as a callback function when a new service request appears.
230  * This function dispatches the corresponding RESTful service.
231  */
232 int rest_invoke_restful_service(void *request, void *response,
233  uint8_t *buffer, uint16_t buffer_size,
234  int32_t *offset);
235 /*---------------------------------------------------------------------------*/
236 /**
237  * \brief Initializes REST framework and starts the HTTP or CoAP process.
238  */
239 void rest_init_engine(void);
240 /*---------------------------------------------------------------------------*/
241 /**
242  *
243  * \brief Resources wanted to be accessible should be activated with the following code.
244  * \param resource
245  * A RESTful resource defined through the RESOURCE macros.
246  * \param path
247  * The local URI path where to provide the resource.
248  */
249 void rest_activate_resource(resource_t *resource, char *path);
250 /*---------------------------------------------------------------------------*/
251 /**
252  * \brief Returns the list of registered RESTful resources.
253  * \return The resource list.
254  */
256 /*---------------------------------------------------------------------------*/
257 
258 #endif /*REST_ENGINE_H_ */
rest_resource_flags_t
Resource flags for allowed methods and special functionalities.
List of Content-Formats which are Internet Media Types plus encoding.
list_t rest_get_resources(void)
Returns the list of registered RESTful resources.
Definition: rest-engine.c:122
A timer.
Definition: etimer.h:76
void ** list_t
The linked list type.
Definition: list.h:133
void rest_activate_resource(resource_t *resource, char *path)
Resources wanted to be accessible should be activated with the following code.
Definition: rest-engine.c:103
Generic status codes that are mapped to either HTTP or CoAP codes.
void rest_init_engine(void)
Initializes REST framework and starts the HTTP or CoAP process.
Definition: rest-engine.c:71
Constants for the REST Engine (Erbium).
static uint8_t accept(uint8_t in)
Processes an incoming or outgoing multicast message and determines whether it should be dropped or ac...
Definition: roll-tm.c:894