/* check if an error was signaled and output payload if so */
if (COAP_RESPONSE_CLASS(code) >= 4) {
- fprintf(stderr, "%d.%02d", (received->hdr->code >> 5), received->hdr->code & 0x1F);
+ fprintf(stderr, "%d.%02d", (code >> 5), code & 0x1F);
if (coap_get_data(received, &len, &databuf)) {
fprintf(stderr, " ");
while (len--) {
coap_tick_t t;
coap_subscription_t *subscription;
+ coap_transport_t transport = COAP_UDP;
+ unsigned short req_code;
+
/* FIXME: return time, e.g. in human-readable by default and ticks
* when query ?ticks is given. */
/* if my_clock_base was deleted, we pretend to have no such resource */
+
+ switch(ctx->protocol) {
+ case COAP_PROTO_UDP:
+ case COAP_PROTO_DTLS:
+ transport = COAP_UDP;
+ break;
+ case COAP_PROTO_TCP:
+ case COAP_PROTO_TLS:
+ transport = coap_get_tcp_header_type_from_size(request->length);
+ break;
+ default:
+ /* Should not enter here */
+ break;
+ }
+
+ req_code = (unsigned short)coap_get_code(response, transport);
+
response->transport_hdr->udp.code = my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404);
- if (request != NULL && coap_check_option(request, COAP_OPTION_OBSERVE, &opt_iter)) {
+ if (request != NULL && coap_check_option2(request, COAP_OPTION_OBSERVE, &opt_iter, transport)) {
subscription = coap_add_observer(resource, peer, token);
if (subscription) {
- subscription->non = request->transport_hdr->udp.type == COAP_MESSAGE_NON;
+ if (ctx->protocol == COAP_PROTO_UDP || ctx->protocol == COAP_PROTO_DTLS) {
+ subscription->non = request->transport_hdr->udp.type == COAP_MESSAGE_NON;
+ } else if (ctx->protocol == COAP_PROTO_TCP || ctx->protocol == COAP_PROTO_TLS) {
+ /* TCP / TLS doesn't have type field on header */
+ subscription->non = 1;
+ } else {
+ /* Should not enter here */
+ }
coap_add_option(response, COAP_OPTION_OBSERVE, 0, NULL);
}
}
coap_ticks(&t);
now = my_clock_base + (t / COAP_TICKS_PER_SECOND);
- if (request != NULL && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter))
+ if (request != NULL && (option = coap_check_option2(request, COAP_OPTION_URI_QUERY, &opt_iter, transport))
&& memcmp(COAP_OPT_VALUE(option), "ticks", min(5, COAP_OPT_LENGTH(option))) == 0) {
/* output ticks */
len = snprintf((char *)buf, min(sizeof(buf), response->max_size - response->length), "%u", (unsigned int)now);
unsigned long delay = 5;
size_t size;
+ coap_opt_filter_t f;
+ coap_transport_t transport = COAP_UDP;
+
+ switch(ctx->protocol) {
+ case COAP_PROTO_UDP:
+ case COAP_PROTO_DTLS:
+ transport = COAP_UDP;
+ break;
+ case COAP_PROTO_TCP:
+ case COAP_PROTO_TLS:
+ transport = coap_get_tcp_header_type_from_size(request->length);
+ break;
+ default:
+ break;
+ }
+
if (async) {
- if (async->id != request->transport_hdr->udp.id) {
- coap_opt_filter_t f;
- coap_option_filter_clear(f);
+
+ coap_option_filter_clear(f);
+ if (ctx->protocol == COAP_PROTO_UDP || ctx->protocol == COAP_PROTO_DTLS) {
+ if (async->id != request->transport_hdr->udp.id) {
+ response->transport_hdr->udp.code = COAP_RESPONSE_CODE(503);
+ }
+ } else if (ctx->protocol == COAP_PROTO_TCP || ctx->protocol == COAP_PROTO_TLS) {
response->transport_hdr->udp.code = COAP_RESPONSE_CODE(503);
+ } else {
+ /* Should not enter here */
}
return;
}
- option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter);
+ option = coap_check_option2(request, COAP_OPTION_URI_QUERY, &opt_iter, transport);
if (option) {
unsigned char *p = COAP_OPT_VALUE(option);
response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM ? COAP_MESSAGE_CON : COAP_MESSAGE_NON, COAP_RESPONSE_CODE(205), 0, size);
if (!response) {
- debug("check_async: insufficient memory, we'll try later\n");
+ debug("check_async : insufficient memory, we'll try later\n");
async->appdata = (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND);
return;
}
coap_add_data(response, 4, (unsigned char *)"done");
- if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) {
- debug("check_async: cannot send response for message %d\n", response->transport_hdr->udp.id);
+ if (ctx->protocol == COAP_PROTO_UDP || ctx->protocol == COAP_PROTO_DTLS) {
+ if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) {
+ debug("check_async : cannot send response for message %d\n", response->transport_hdr->udp.id);
+ }
+ coap_delete_pdu(response);
+ } else if (ctx->protocol == COAP_PROTO_TCP || ctx->protocol == COAP_PROTO_TLS) {
+ coap_pdu_t *tcp_resp = NULL;
+ tcp_resp = coap_convert_to_tcp_pdu(response);
+ if (tcp_resp != NULL) {
+ warn("check_async : failed to create tcp response\n");
+ } else {
+ if (coap_send(ctx, &async->peer, tcp_resp) == COAP_INVALID_TID) {
+ debug("check_async : cannot send TCP response for message %d\n", response->transport_hdr->udp.id);
+ }
+ coap_delete_pdu(tcp_resp);
+ }
+ } else {
+ /* Should not enter here */
}
- coap_delete_pdu(response);
+
coap_remove_async(ctx, async->id, &tmp);
coap_free_async(async);
async = NULL;
#include <apps/netutils/libcoap/debug.h>
#include <apps/netutils/libcoap/async.h>
-/* TODO : Considering TCP Case */
coap_async_state_t *coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request, unsigned char flags, void *data)
{
coap_async_state_t *s;
coap_tid_t id;
+ coap_transport_t transport = COAP_UDP;
+
+ unsigned char *token;
+ unsigned int token_len = 0;
+
+ switch(context->protocol) {
+ case COAP_PROTO_UDP:
+ case COAP_PROTO_DTLS:
+ transport = COAP_UDP;
+ break;
+ case COAP_PROTO_TCP:
+ case COAP_PROTO_TLS:
+ transport = coap_get_tcp_header_type_from_size(request->length);
+ break;
+ default:
+ break;
+ }
+
coap_transaction_id2(peer, request, &id, context->protocol);
LL_SEARCH_SCALAR(context->async_state, s, id, id);
+ coap_get_token2(request->transport_hdr, transport, &token, &token_len);
+
+ if (token_len > 8) {
+ debug("coap_register_async : invalied length of token\n");
+ return NULL;
+ }
+
if (s != NULL) {
/* We must return NULL here as the caller must know that he is
* responsible for releasing @p data. */
- debug("asynchronous state for transaction %d already registered\n", id);
+ debug("coap_register_async : asynchronous state for transaction %d already registered\n", id);
return NULL;
}
/* store information for handling the asynchronous task */
- s = (coap_async_state_t *) coap_malloc(sizeof(coap_async_state_t) +
- request->transport_hdr->udp.token_length);
+ s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t) + token_len);
if (!s) {
- coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
+ coap_log(LOG_CRIT, "coap_register_async : insufficient memory\n");
return NULL;
}
- memset(s, 0, sizeof(coap_async_state_t) + request->transport_hdr->udp.token_length);
+ memset(s, 0, sizeof(coap_async_state_t) + token_len);
/* set COAP_ASYNC_CONFIRM according to request's type */
s->flags = flags & ~COAP_ASYNC_CONFIRM;
- if (request->transport_hdr->udp.type == COAP_MESSAGE_CON) {
- s->flags |= COAP_ASYNC_CONFIRM;
+ if (context->protocol == COAP_PROTO_UDP || context->protocol == COAP_PROTO_TCP) {
+ if (request->transport_hdr->udp.type == COAP_MESSAGE_CON) {
+ s->flags |= COAP_ASYNC_CONFIRM;
+ }
}
s->appdata = data;
memcpy(&s->peer, peer, sizeof(coap_address_t));
- if (request->transport_hdr->udp.token_length) {
- s->tokenlen = request->transport_hdr->udp.token_length;
- memcpy(s->token, request->transport_hdr->udp.token, request->transport_hdr->udp.token_length);
+ if (token_len) {
+ s->tokenlen = token_len;
+ memcpy(s->token, token, token_len);
}
memcpy(&s->id, &id, sizeof(coap_tid_t));
transport = coap_get_tcp_header_type_from_initbyte(((unsigned char *)buf)[0] >> 4);
debug("coap_read : received header type, transport %d, len %u, bytes_read %d\n", transport, ((buf[0] >> 4) & 0x0f), bytes_read);
if (!coap_pdu_parse2((unsigned char*)buf, bytes_read, node->pdu, transport)) {
- warn("coap_read : discard malformed TCP PDU\n");
+ /* FIXME : prevent printing log when continuously received wrong PDU */
+ //warn("coap_read : discard malformed TCP PDU\n");
goto error;
}
node->transport = transport;
coap_method_handler_t h;
coap_subscription_t *obs;
str token;
- coap_pdu_t *response;
+ coap_pdu_t *response = NULL;
+ coap_pdu_t *tcp_resp = NULL;
if (r->observable && (r->dirty || r->partiallydirty)) {
r->partiallydirty = 0;
token.length = obs->token_length;
token.s = obs->token;
- /* TODO : Considering TCP Case */
+
response->transport_hdr->udp.id = coap_new_message_id(context);
if (obs->non && obs->non_cnt < COAP_OBS_MAX_NON) {
response->transport_hdr->udp.type = COAP_MESSAGE_NON;
/* fill with observer-specific data */
h(context, r, &obs->subscriber, NULL, &token, response);
- if (response->transport_hdr->udp.type == COAP_MESSAGE_CON) {
- tid = coap_send_confirmed(context, &obs->subscriber, response);
- obs->non_cnt = 0;
- } else {
- tid = coap_send(context, &obs->subscriber, response);
- obs->non_cnt++;
- }
+ switch (context->protocol) {
+ case COAP_PROTO_UDP:
+ case COAP_PROTO_DTLS:
+ if (response->transport_hdr->udp.type == COAP_MESSAGE_CON) {
+ tid = coap_send_confirmed(context, &obs->subscriber, response);
+ obs->non_cnt = 0;
+ } else {
+ tid = coap_send(context, &obs->subscriber, response);
+ obs->non_cnt++;
+ }
- if (COAP_INVALID_TID == tid || response->transport_hdr->udp.type != COAP_MESSAGE_CON) {
- coap_delete_pdu(response);
+ if (COAP_INVALID_TID == tid ||
+ response->transport_hdr->udp.type != COAP_MESSAGE_CON) {
+ coap_delete_pdu(response);
+ }
+ break;
+ case COAP_PROTO_TCP:
+ case COAP_PROTO_TLS:
+ tcp_resp = coap_convert_to_tcp_pdu(response);
+ if (tcp_resp == NULL) {
+ warn("coap_check_notify : failed to create TCP response\n");
+ } else {
+ tid = coap_send(context, &obs->subscriber, tcp_resp);
+ if (COAP_INVALID_TID == tid) {
+ coap_delete_pdu(tcp_resp);
+ }
+ }
+ break;
+ default:
+ /* Should not enter here */
+ break;
}
+
if (COAP_INVALID_TID == tid) {
debug("coap_check_notify: sending failed, resource stays partially dirty\n");
obs->dirty = 1;