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 #ifndef MIN
66 #define MIN(a, b) ((a) < (b) ? (a) : (b))
67 #endif /* MIN */
68 
69 struct resource_s;
70 struct periodic_resource_s;
71 
72 /* signatures of handler functions */
73 typedef void (*restful_handler)(void *request, void *response,
74  uint8_t *buffer, uint16_t preferred_size,
75  int32_t *offset);
76 typedef void (*restful_final_handler)(struct resource_s *resource,
77  void *request, void *response);
78 typedef void (*restful_periodic_handler)(void);
79 typedef void (*restful_response_handler)(void *data, void *response);
80 typedef void (*restful_trigger_handler)(void);
81 
82 /* signature of the rest-engine service function */
83 typedef int (*service_callback_t)(void *request, void *response,
84  uint8_t *buffer, uint16_t preferred_size,
85  int32_t *offset);
86 
87 /* data structure representing a resource in REST */
88 struct resource_s {
89  struct resource_s *next; /* for LIST, points to next resource defined */
90  const char *url; /*handled URL */
91  rest_resource_flags_t flags; /* handled RESTful methods */
92  const char *attributes; /* link-format attributes */
93  restful_handler get_handler; /* handler function */
94  restful_handler post_handler; /* handler function */
95  restful_handler put_handler; /* handler function */
96  restful_handler delete_handler; /* handler function */
97  union {
98  struct periodic_resource_s *periodic; /* special data depending on flags */
99  restful_trigger_handler trigger;
100  restful_trigger_handler resume;
101  };
102 };
103 typedef struct resource_s resource_t;
104 
105 struct periodic_resource_s {
106  struct periodic_resource_s *next; /* for LIST, points to next resource defined */
107  const resource_t *resource;
108  uint32_t period;
109  struct etimer periodic_timer;
110  const restful_periodic_handler periodic_handler;
111 };
112 typedef struct periodic_resource_s periodic_resource_t;
113 
114 /*
115  * Macro to define a RESTful resource.
116  * Resources are statically defined for the sake of efficiency and better memory management.
117  */
118 #define RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \
119  resource_t name = { NULL, NULL, NO_FLAGS, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } }
120 
121 #define PARENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler) \
122  resource_t name = { NULL, NULL, HAS_SUB_RESOURCES, attributes, get_handler, post_handler, put_handler, delete_handler, { NULL } }
123 
124 #define SEPARATE_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, resume_handler) \
125  resource_t name = { NULL, NULL, IS_SEPARATE, attributes, get_handler, post_handler, put_handler, delete_handler, { .resume = resume_handler } }
126 
127 #define EVENT_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, event_handler) \
128  resource_t name = { NULL, NULL, IS_OBSERVABLE, attributes, get_handler, post_handler, put_handler, delete_handler, { .trigger = event_handler } }
129 
130 /*
131  * Macro to define a periodic resource.
132  * The corresponding [name]_periodic_handler() function will be called every period.
133  * For instance polling a sensor and publishing a changed value to subscribed clients would be done there.
134  * The subscriber list will be maintained by the final_handler rest_subscription_handler() (see rest-mapping header file).
135  */
136 #define PERIODIC_RESOURCE(name, attributes, get_handler, post_handler, put_handler, delete_handler, period, periodic_handler) \
137  periodic_resource_t periodic_##name; \
138  resource_t name = { NULL, NULL, IS_OBSERVABLE | IS_PERIODIC, attributes, get_handler, post_handler, put_handler, delete_handler, { .periodic = &periodic_##name } }; \
139  periodic_resource_t periodic_##name = { NULL, &name, period, { { 0 } }, periodic_handler };
140 
141 struct rest_implementation {
142  char *name;
143 
144  /** Initialize the REST implementation. */
145  void (*init)(void);
146 
147  /** Register the RESTful service callback at implementation. */
148  void (*set_service_callback)(service_callback_t callback);
149 
150  /** Get request URI path. */
151  int (*get_url)(void *request, const char **url);
152 
153  /** Get the method of a request. */
154  rest_resource_flags_t (*get_method_type)(void *request);
155 
156  /** Set the status code of a response. */
157  int (*set_response_status)(void *response, unsigned int code);
158 
159  /** Get the content-type of a request. */
160  int (*get_header_content_type)(void *request,
161  unsigned int *content_format);
162 
163  /** Set the Content-Type of a response. */
164  int (*set_header_content_type)(void *response,
165  unsigned int content_format);
166 
167  /** Get the Accept types of a request. */
168  int (*get_header_accept)(void *request, unsigned int *accept);
169 
170  /** Get the Length option of a request. */
171  int (*get_header_length)(void *request, uint32_t *size);
172 
173  /** Set the Length option of a response. */
174  int (*set_header_length)(void *response, uint32_t size);
175 
176  /** Get the Max-Age option of a request. */
177  int (*get_header_max_age)(void *request, uint32_t *age);
178 
179  /** Set the Max-Age option of a response. */
180  int (*set_header_max_age)(void *response, uint32_t age);
181 
182  /** Set the ETag option of a response. */
183  int (*set_header_etag)(void *response, const uint8_t *etag,
184  size_t length);
185 
186  /** Get the If-Match option of a request. */
187  int (*get_header_if_match)(void *request, const uint8_t **etag);
188 
189  /** Get the If-Match option of a request. */
190  int (*get_header_if_none_match)(void *request);
191 
192  /** Get the Host option of a request. */
193  int (*get_header_host)(void *request, const char **host);
194 
195  /** Set the location option of a response. */
196  int (*set_header_location)(void *response, const char *location);
197 
198  /** Get the payload option of a request. */
199  int (*get_request_payload)(void *request, const uint8_t **payload);
200 
201  /** Set the payload option of a response. */
202  int (*set_response_payload)(void *response, const void *payload,
203  size_t length);
204 
205  /** Get the query string of a request. */
206  int (*get_query)(void *request, const char **value);
207 
208  /** Get the value of a request query key-value pair. */
209  int (*get_query_variable)(void *request, const char *name,
210  const char **value);
211 
212  /** Get the value of a request POST key-value pair. */
213  int (*get_post_variable)(void *request, const char *name,
214  const char **value);
215 
216  /** Send the payload to all subscribers of the resource at url. */
217  void (*notify_subscribers)(resource_t *resource);
218 
219  /** The handler for resource subscriptions. */
220  restful_final_handler subscription_handler;
221 
222  /* REST status codes. */
223  const struct rest_implementation_status status;
224 
225  /* REST content-types. */
226  const struct rest_implementation_type type;
227 };
228 
229 /* instance of REST implementation */
230 extern const struct rest_implementation REST;
231 
232 /*
233  * To be called by HTTP/COAP server as a callback function when a new service request appears.
234  * This function dispatches the corresponding RESTful service.
235  */
236 int rest_invoke_restful_service(void *request, void *response,
237  uint8_t *buffer, uint16_t buffer_size,
238  int32_t *offset);
239 /*---------------------------------------------------------------------------*/
240 /**
241  * \brief Initializes REST framework and starts the HTTP or CoAP process.
242  */
243 void rest_init_engine(void);
244 /*---------------------------------------------------------------------------*/
245 /**
246  *
247  * \brief Resources wanted to be accessible should be activated with the following code.
248  * \param resource
249  * A RESTful resource defined through the RESOURCE macros.
250  * \param path
251  * The local URI path where to provide the resource.
252  */
253 void rest_activate_resource(resource_t *resource, char *path);
254 /*---------------------------------------------------------------------------*/
255 /**
256  * \brief Returns the list of registered RESTful resources.
257  * \return The resource list.
258  */
260 /*---------------------------------------------------------------------------*/
261 
262 #endif /*REST_ENGINE_H_ */
list_t rest_get_resources(void)
Returns the list of registered RESTful resources.
Definition: rest-engine.c:113
rest_resource_flags_t
Resource flags for allowed methods and special functionalities.
void ** list_t
The linked list type.
Definition: list.h:133
List of Content-Formats which are Internet Media Types plus encoding.
Constants for the REST Engine (Erbium).
Generic status codes that are mapped to either HTTP or CoAP codes.
void rest_activate_resource(resource_t *resource, char *path)
Makes a resource available under the given URI path.
Definition: rest-engine.c:94
void rest_init_engine(void)
Initializes and starts the REST Engine process.
Definition: rest-engine.c:71
A timer.
Definition: etimer.h:76