Contiki-NG
Loading...
Searching...
No Matches
coap-callback-api.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016, SICS Swedish ICT
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 *
30 */
31
32/**
33 * \file
34 * Callback API for doing CoAP requests.
35 * Adapted from the blocking API.
36 * \author
37 * Joakim Eriksson, joakime@sics.se
38 */
39
40/**
41 * \addtogroup coap
42 * @{
43 */
44
45#include "coap-engine.h"
46#include "coap-callback-api.h"
47#include "coap-transactions.h"
48#include "sys/cc.h"
49#include <stdlib.h>
50#include <string.h>
51#include <inttypes.h>
52
53/* Log configuration */
54#include "coap-log.h"
55#define LOG_MODULE "coap"
56#define LOG_LEVEL LOG_LEVEL_COAP
57
58static void coap_request_callback(void *callback_data, coap_message_t *response);
59
60/*---------------------------------------------------------------------------*/
61
62static int
63progress_request(coap_callback_request_state_t *callback_state) {
64 coap_request_state_t *state = &callback_state->state;
65 coap_message_t *request = state->request;
66 request->mid = coap_get_mid();
67 if((state->transaction =
68 coap_new_transaction(request->mid, state->remote_endpoint))) {
69 state->transaction->callback = coap_request_callback;
70 state->transaction->callback_data = state;
71
72 if(state->block_num > 0) {
73 coap_set_header_block2(request, state->block_num, 0,
74 COAP_MAX_CHUNK_SIZE);
75 }
76 state->transaction->message_len =
77 coap_serialize_message(request, state->transaction->message);
78
79 coap_send_transaction(state->transaction);
80 LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid);
81 return 1;
82 }
83 return 0;
84}
85
86/*---------------------------------------------------------------------------*/
87
88static void
89coap_request_callback(void *callback_data, coap_message_t *response)
90{
91 coap_callback_request_state_t *callback_state = (coap_callback_request_state_t*)callback_data;
92 coap_request_state_t *state = &callback_state->state;
93
94 state->response = response;
95
96 LOG_DBG("request callback\n");
97
98 if(!state->response) {
99 LOG_WARN("Server not responding giving up...\n");
100 state->status = COAP_REQUEST_STATUS_TIMEOUT;
101 callback_state->callback(callback_state);
102 return;
103 }
104
105 /* Got a response */
106 coap_get_header_block2(state->response, &state->res_block, &state->more, NULL, NULL);
107 uint32_t res_block1 = 0;
108 coap_get_header_block1(state->response, &res_block1, NULL, NULL, NULL);
109
110 LOG_DBG("Received #%lu%s B1:%lu (%u bytes)\n",
111 (unsigned long)state->res_block, (unsigned)state->more ? "+" : "",
112 (unsigned long)res_block1,
113 state->response->payload_len);
114
115 if(state->res_block == state->block_num) {
116 /* Call the callback function as we have more data */
117 if(state->more) {
118 state->status = COAP_REQUEST_STATUS_MORE;
119 } else {
120 state->status = COAP_REQUEST_STATUS_RESPONSE;
121 }
122 callback_state->callback(callback_state);
123 /* this is only for counting BLOCK2 blocks.*/
124 ++(state->block_num);
125 } else {
126 LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n", state->res_block, state->block_num);
127 ++(state->block_error);
128 }
129
130 if(state->more) {
131 if((state->block_error) < COAP_MAX_ATTEMPTS) {
132 progress_request(callback_state);
133 } else {
134 /* failure - now we give up and notify the callback */
135 state->status = COAP_REQUEST_STATUS_BLOCK_ERROR;
136 callback_state->callback(callback_state);
137 }
138 } else {
139 /* No more blocks, finish and notify the callback */
140 state->status = COAP_REQUEST_STATUS_FINISHED;
141 state->response = NULL;
142 callback_state->callback(callback_state);
143 }
144}
145
146/*---------------------------------------------------------------------------*/
147
148int
149coap_send_request(coap_callback_request_state_t *callback_state, coap_endpoint_t *endpoint,
150 coap_message_t *request,
151 void (*callback)(coap_callback_request_state_t *callback_state))
152{
153 coap_request_state_t *state = &callback_state->state;
154
155 state->more = 0;
156 state->res_block = 0;
157 state->block_error = 0;
158 state->block_num = 0;
159 state->response = NULL;
160 state->request = request;
161 state->remote_endpoint = endpoint;
162 callback_state->callback = callback;
163
164 return progress_request(callback_state);
165}
166/*---------------------------------------------------------------------------*/
167/** @} */
Default definitions of C compiler quirk work-arounds.
Callback API for doing CoAP requests Adapted from the blocking API.
CoAP engine implementation.
Log support for CoAP.
CoAP module for reliable transport.
int coap_send_request(coap_callback_request_state_t *callback_state, coap_endpoint_t *endpoint, coap_message_t *request, void(*callback)(coap_callback_request_state_t *callback_state))
Send a CoAP request to a remote endpoint.