Contiki-NG
coap-blocking-api.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 * CoAP implementation for the REST Engine.
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 "coap-blocking-api.h"
46#include "sys/cc.h"
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <inttypes.h>
51
52/* Log configuration */
53#include "coap-log.h"
54#define LOG_MODULE "coap"
55#define LOG_LEVEL LOG_LEVEL_COAP
56
57/*---------------------------------------------------------------------------*/
58/*- Client Part -------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60void
61coap_blocking_request_callback(void *callback_data, coap_message_t *response)
62{
63 coap_blocking_request_state_t *blocking_state = (coap_blocking_request_state_t *)callback_data;
64
65 blocking_state->state.response = response;
66 process_poll(blocking_state->process);
67}
68/*---------------------------------------------------------------------------*/
69PT_THREAD(coap_blocking_request
70 (coap_blocking_request_state_t *blocking_state, process_event_t ev,
71 coap_endpoint_t *remote_ep,
72 coap_message_t *request,
73 coap_blocking_response_handler_t request_callback))
74{
75 /* Before PT_BEGIN in order to not be a local variable in the PT_Thread and maintain it */
76 coap_request_state_t *state = &blocking_state->state;
77
78 PT_BEGIN(&blocking_state->pt);
79
80 state->block_num = 0;
81 state->response = NULL;
82 blocking_state->process = PROCESS_CURRENT();
83
84 state->more = 0;
85 state->res_block = 0;
86 state->block_error = 0;
87
88 do {
89 request->mid = coap_get_mid();
90 if((state->transaction = coap_new_transaction(request->mid, remote_ep))) {
91 state->transaction->callback = coap_blocking_request_callback;
92 state->transaction->callback_data = blocking_state;
93
94 if(state->block_num > 0) {
95 coap_set_header_block2(request, state->block_num, 0,
96 COAP_MAX_CHUNK_SIZE);
97 }
98 state->transaction->message_len = coap_serialize_message(request,
99 state->
100 transaction->
101 message);
102
103 coap_send_transaction(state->transaction);
104 LOG_DBG("Requested #%"PRIu32" (MID %u)\n", state->block_num, request->mid);
105
106 PT_YIELD_UNTIL(&blocking_state->pt, ev == PROCESS_EVENT_POLL);
107
108 if(!state->response) {
109 LOG_WARN("Server not responding\n");
110 state->status = COAP_REQUEST_STATUS_TIMEOUT;
111 request_callback(NULL); /* Call the callback with NULL to signal timeout */
112 PT_EXIT(&blocking_state->pt);
113 }
114
115 coap_get_header_block2(state->response, &state->res_block, &state->more, NULL, NULL);
116
117 LOG_DBG("Received #%"PRIu32"%s (%u bytes)\n", state->res_block, state->more ? "+" : "",
118 state->response->payload_len);
119 if(state->more) {
120 state->status = COAP_REQUEST_STATUS_MORE;
121 } else {
122 state->status = COAP_REQUEST_STATUS_RESPONSE;
123 }
124
125 if(state->res_block == state->block_num) {
126 request_callback(state->response);
127 ++(state->block_num);
128 } else {
129 LOG_WARN("WRONG BLOCK %"PRIu32"/%"PRIu32"\n",
130 state->res_block, state->block_num);
131 ++(state->block_error);
132 }
133 } else {
134 LOG_WARN("Could not allocate transaction buffer");
135 PT_EXIT(&blocking_state->pt);
136 }
137 } while(state->more && (state->block_error) < COAP_MAX_ATTEMPTS);
138
139 if((state->block_error) >= COAP_MAX_ATTEMPTS) {
140 /* failure - now we give up */
141 state->status = COAP_REQUEST_STATUS_BLOCK_ERROR;
142 } else {
143 /* No more blocks, request finished */
144 state->status = COAP_REQUEST_STATUS_FINISHED;
145 }
146 PT_END(&blocking_state->pt);
147}
148/*---------------------------------------------------------------------------*/
149/** @} */
Default definitions of C compiler quirk work-arounds.
CoAP engine implementation.
Log support for CoAP.
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
Definition: process.h:402
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define PT_THREAD(name_args)
Declaration of a protothread.
Definition: pt.h:265
#define PT_EXIT(pt)
Exit the protothread.
Definition: pt.h:411
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Definition: pt.h:280
#define PT_END(pt)
Declare the end of a protothread.
Definition: pt.h:292
#define PT_YIELD_UNTIL(pt, cond)
Yield from the protothread until a condition occurs.
Definition: pt.h:475