Contiki-NG
Loading...
Searching...
No Matches
coap-res-well-known-core.c
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 * /.well-known/core resource implementation.
35 * \author
36 * Matthias Kovatsch <kovatsch@inf.ethz.ch>
37 */
38
39/**
40 * \addtogroup coap
41 * @{
42 */
43
44#include "coap-engine.h"
45#include <string.h>
46#include <stdio.h>
47
48/* Log configuration */
49#include "coap-log.h"
50#define LOG_MODULE "coap"
51#define LOG_LEVEL LOG_LEVEL_COAP
52
53#define ADD_CHAR_IF_POSSIBLE(char) \
54 if(strpos >= *offset && bufpos < preferred_size) { \
55 buffer[bufpos++] = char; \
56 } \
57 ++strpos
58
59#define ADD_STRING_IF_POSSIBLE(string, op) \
60 tmplen = strlen(string); \
61 if(strpos + tmplen > *offset) { \
62 bufpos += snprintf((char *)buffer + bufpos, \
63 preferred_size - bufpos + 1, \
64 "%s", \
65 string \
66 + (*offset - (int32_t)strpos > 0 ? \
67 *offset - (int32_t)strpos : 0)); \
68 if(bufpos op preferred_size) { \
69 LOG_DBG("BREAK at %s (%p)\n", string, resource); \
70 break; \
71 } \
72 } \
73 strpos += tmplen
74
75/*---------------------------------------------------------------------------*/
76/*- Resource Handlers -------------------------------------------------------*/
77/*---------------------------------------------------------------------------*/
78static void
79well_known_core_get_handler(coap_message_t *request, coap_message_t *response,
80 uint8_t *buffer, uint16_t preferred_size,
81 int32_t *offset)
82{
83 size_t strpos = 0; /* position in overall string (which is larger than the buffer) */
84 size_t bufpos = 0; /* position within buffer (bytes written) */
85 size_t tmplen = 0;
86 coap_resource_t *resource = NULL;
87
88#if COAP_LINK_FORMAT_FILTERING
89 /* For filtering. */
90 const char *filter = NULL;
91 const char *attrib = NULL;
92 const char *found = NULL;
93 const char *end = NULL;
94 char *value = NULL;
95 char lastchar = '\0';
96 int len = coap_get_header_uri_query(request, &filter);
97
98 if(len) {
99 value = strchr(filter, '=');
100 value[0] = '\0';
101 ++value;
102 len -= strlen(filter) + 1;
103
104 LOG_DBG("Filter %s = ", filter);
105 LOG_DBG_COAP_STRING(value, len);
106 LOG_DBG_("\n");
107
108 if(strcmp(filter, "href") == 0 && value[0] == '/') {
109 ++value;
110 --len;
111 }
112
113 lastchar = value[len - 1];
114 value[len - 1] = '\0';
115 }
116#endif /* COAP_LINK_FORMAT_FILTERING */
117
118 for(resource = coap_get_first_resource(); resource;
119 resource = coap_get_next_resource(resource)) {
120#if COAP_LINK_FORMAT_FILTERING
121 /* Filtering */
122 if(len) {
123 if(strcmp(filter, "href") == 0) {
124 attrib = strstr(resource->url, value);
125 if(attrib == NULL || (value[-1] == '/' && attrib != resource->url)) {
126 continue;
127 }
128 end = attrib + strlen(attrib);
129 } else if(resource->attributes != NULL) {
130 attrib = strstr(resource->attributes, filter);
131 if(attrib == NULL
132 || (attrib[strlen(filter)] != '='
133 && attrib[strlen(filter)] != '"')) {
134 continue;
135 }
136 attrib += strlen(filter) + 2;
137 end = strchr(attrib, '"');
138 }
139
140 LOG_DBG("Filter: res has attrib %s (%s)\n", attrib, value);
141 found = attrib;
142 while((found = strstr(found, value)) != NULL) {
143 if(found > end) {
144 found = NULL;
145 break;
146 }
147 if(lastchar == found[len - 1] || lastchar == '*') {
148 break;
149 }
150 ++found;
151 }
152 if(found == NULL) {
153 continue;
154 }
155 LOG_DBG("Filter: res has prefix %s\n", found);
156 if(lastchar != '*'
157 && (found[len] != '"' && found[len] != ' ' && found[len] != '\0')) {
158 continue;
159 }
160 LOG_DBG("Filter: res has match\n");
161 }
162#endif
163
164 LOG_DBG("/%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource,
165 strpos, (long)*offset, bufpos);
166
167 if(strpos > 0) {
168 ADD_CHAR_IF_POSSIBLE(',');
169 }
170 ADD_CHAR_IF_POSSIBLE('<');
171 ADD_CHAR_IF_POSSIBLE('/');
172 ADD_STRING_IF_POSSIBLE(resource->url, >=);
173 ADD_CHAR_IF_POSSIBLE('>');
174
175 if(resource->attributes != NULL && resource->attributes[0]) {
176 ADD_CHAR_IF_POSSIBLE(';');
177 ADD_STRING_IF_POSSIBLE(resource->attributes, >);
178 }
179
180 /* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */
181 if(bufpos > preferred_size && strpos - bufpos > *offset) {
182 LOG_DBG("BREAK at %s (%p)\n", resource->url, resource);
183 break;
184 }
185 }
186
187 if(bufpos > 0) {
188 LOG_DBG("BUF %zu: ", bufpos);
189 LOG_DBG_COAP_STRING((char *)buffer, bufpos);
190 LOG_DBG_("\n");
191
192 coap_set_payload(response, buffer, bufpos);
193 coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);
194 } else if(strpos > 0) {
195 LOG_DBG("well_known_core_handler(): bufpos<=0\n");
196
197 coap_set_status_code(response, BAD_OPTION_4_02);
198 coap_set_payload(response, "BlockOutOfScope", 15);
199 }
200
201 if(resource == NULL) {
202 LOG_DBG("DONE\n");
203 *offset = -1;
204 } else {
205 LOG_DBG("MORE at %s (%p)\n", resource->url, resource);
206 *offset += preferred_size;
207 }
208}
209/*---------------------------------------------------------------------------*/
210RESOURCE(res_well_known_core, "ct=40", well_known_core_get_handler, NULL,
211 NULL, NULL);
212/*---------------------------------------------------------------------------*/
213/** @} */
CoAP engine implementation.
Log support for CoAP.
coap_resource_t * coap_get_next_resource(coap_resource_t *resource)
Returns the next registered CoAP resource.
coap_resource_t * coap_get_first_resource(void)
Returns the first of the registered CoAP resources.