1 /*
2 * server-coap.h -- LwIP example
3 *
4 * Copyright (C) 2013-2016 Christian Amsüss <chrysn@fsfe.org>
5 * Copyright (C) 2018-2021 Jon Shallow <supjps-libcoap@jpshallow.com>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * This file is part of the CoAP library libcoap. Please see README for terms
10 * of use.
11 */
12
13 #include "coap_config.h"
14 #include <coap3/coap.h>
15
16 coap_context_t *main_coap_context;
17
18 static coap_time_t clock_offset;
19 /* changeable clock base (see handle_put_time()) */
20 static coap_time_t my_clock_base = 0;
21 static coap_resource_t *time_resource = NULL; /* just for testing */
22
23 #ifndef min
24 # define min(a,b) ((a) < (b) ? (a) : (b))
25 #endif
26
27 void
hnd_get_time(coap_resource_t * resource,coap_session_t * session,const coap_pdu_t * request,const coap_string_t * query,coap_pdu_t * response)28 hnd_get_time(coap_resource_t *resource, coap_session_t *session,
29 const coap_pdu_t *request, const coap_string_t *query,
30 coap_pdu_t *response) {
31 unsigned char buf[40];
32 size_t len;
33 coap_tick_t now;
34 coap_tick_t t;
35
36 /* FIXME: return time, e.g. in human-readable by default and ticks
37 * when query ?ticks is given. */
38
39 /* if my_clock_base was deleted, we pretend to have no such resource */
40 response->code =
41 my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404);
42
43 if (my_clock_base)
44 coap_add_option(response, COAP_OPTION_CONTENT_FORMAT,
45 coap_encode_var_safe(buf, sizeof(buf),
46 COAP_MEDIATYPE_TEXT_PLAIN),
47 buf);
48
49 coap_add_option(response, COAP_OPTION_MAXAGE,
50 coap_encode_var_safe(buf, sizeof(buf), 0x01), buf);
51
52 if (my_clock_base) {
53
54 /* calculate current time */
55 coap_ticks(&t);
56 now = my_clock_base + (t / COAP_TICKS_PER_SECOND);
57
58
59 if (query != NULL
60 && coap_string_equal(query, coap_make_str_const("ticks"))) {
61 /* output ticks */
62 len = snprintf((char *)buf, sizeof(buf), "%u", (unsigned int)now);
63 coap_add_data(response, len, buf);
64 }
65 }
66 }
67
68 void
init_coap_resources(coap_context_t * ctx)69 init_coap_resources(coap_context_t *ctx) {
70 coap_resource_t *r;
71 #if 0
72 r = coap_resource_init(NULL, 0, 0);
73 coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index);
74
75 coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
76 coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"General Info\""), 0);
77 coap_add_resource(ctx, r);
78 #endif
79 /* store clock base to use in /time */
80 my_clock_base = clock_offset;
81
82 r = coap_resource_init(coap_make_str_const("time"), 0);
83 if (!r)
84 goto error;
85
86 coap_resource_set_get_observable(r, 1);
87 time_resource = r;
88 coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time);
89 #if 0
90 coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time);
91 coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time);
92 #endif
93 coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
94 /* coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"Internal Clock\""), 0); */
95 coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"ticks\""), 0);
96 coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), 0);
97
98 coap_add_resource(ctx, r);
99 #if 0
100 #ifndef WITHOUT_ASYNC
101 r = coap_resource_init(coap_make_str_const("async"), 0);
102 coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async);
103
104 coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
105 coap_add_resource(ctx, r);
106 #endif /* WITHOUT_ASYNC */
107 #endif
108
109 return;
110 error:
111 coap_log(LOG_CRIT, "cannot create resource\n");
112 }
113
server_coap_init(void)114 void server_coap_init(void)
115 {
116 coap_address_t listenaddress;
117
118 coap_address_init(&listenaddress);
119
120 /* looks like a server address, but is used as end point for clients too */
121 listenaddress.addr = *(IP_ANY_TYPE);
122 listenaddress.port = COAP_DEFAULT_PORT;
123
124 coap_set_log_level(LOG_DEBUG);
125 main_coap_context = coap_new_context(&listenaddress);
126
127 LWIP_ASSERT("Failed to initialize context", main_coap_context != NULL);
128 clock_offset = 1; /* Need a non-zero value */
129 init_coap_resources(main_coap_context);
130 }
131
server_coap_poll(void)132 void server_coap_poll(void)
133 {
134 static coap_time_t last_time = 0;
135 coap_tick_t ticks_now;
136 coap_time_t time_now;
137
138 coap_ticks(&ticks_now);
139 time_now = coap_ticks_to_rt(ticks_now);
140
141 if (last_time != time_now) {
142 /* This takes place once a second */
143 last_time = time_now;
144 coap_resource_notify_observers(time_resource, NULL);
145 }
146 coap_check_notify(main_coap_context);
147 }
148