void hnd_get_rd(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response, void *userdata) { unsigned char buf[3]; response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); }
void hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { unsigned char buf[3]; response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX); }
static void make_bad_request(CoAPCallback &callback, int code) { unsigned char buf[3]; coap_pdu_t *response = (coap_pdu_t*)callback.response_; response->hdr->code = COAP_RESPONSE_CODE(code); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); }
int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu, size_t data_length) { size_t start, want, avail; unsigned char buf[3]; assert(pdu); /* Block2 */ if (type != COAP_OPTION_BLOCK2) { warn("coap_write_block_opt: skipped unknown option\n"); return -1; } start = block->num << (block->szx + 4); if (data_length <= start) { debug("illegal block requested\n"); return -2; } avail = pdu->max_size - pdu->length - 4; want = 1 << (block->szx + 4); /* check if entire block fits in message */ if (want <= avail) { block->m = want < data_length - start; } else { /* Sender has requested a block that is larger than the remaining * space in pdu. This is ok if the remaining data fits into the pdu * anyway. The block size needs to be adjusted only if there is more * data left that cannot be delivered in this message. */ if (data_length - start <= avail) { /* it's the final block and everything fits in the message */ block->m = 0; } else { unsigned char szx; /* we need to decrease the block size */ if (avail < 16) { /* bad luck, this is the smallest block size */ debug("not enough space, even the smallest block does not fit"); return -3; } debug("decrease block size for %d to %d\n", avail, coap_fls(avail) - 5); szx = block->szx; block->szx = coap_fls(avail) - 5; block->m = 1; block->num <<= szx - block->szx; } } /* to re-encode the block option */ coap_add_option(pdu, type, coap_encode_var_bytes(buf, ((block->num << 4) | (block->m << 3) | block->szx)), buf); return 1; }
coap_list_t *CACreateNewOptionNode(uint16_t key, uint32_t length, const char *data) { OIC_LOG(DEBUG, TAG, "IN"); if (!data) { OIC_LOG(ERROR, TAG, "invalid pointer parameter"); return NULL; } coap_option *option = coap_malloc(sizeof(coap_option) + length + 1); if (!option) { OIC_LOG(ERROR, TAG, "Out of memory"); return NULL; } memset(option, 0, sizeof(coap_option) + length + 1); COAP_OPTION_KEY(*option) = key; coap_option_def_t* def = coap_opt_def(key); if (NULL != def && coap_is_var_bytes(def)) { if (length > def->max) { // make sure we shrink the value so it fits the coap option definition // by truncating the value, disregard the leading bytes. OIC_LOG_V(DEBUG, TAG, "Option [%d] data size [%d] shrunk to [%d]", def->key, length, def->max); data = &(data[length-def->max]); length = def->max; } // Shrink the encoding length to a minimum size for coap // options that support variable length encoding. COAP_OPTION_LENGTH(*option) = coap_encode_var_bytes( COAP_OPTION_DATA(*option), coap_decode_var_bytes((unsigned char *)data, length)); } else { COAP_OPTION_LENGTH(*option) = length; memcpy(COAP_OPTION_DATA(*option), data, length); } /* we can pass NULL here as delete function since option is released automatically */ coap_list_t *node = coap_new_listnode(option, NULL); if (!node) { OIC_LOG(ERROR, TAG, "node is NULL"); coap_free(option); return NULL; } OIC_LOG(DEBUG, TAG, "OUT"); return node; }
void CAParseURI(const char* uriInfo, coap_list_t **optlist) { OIC_LOG(DEBUG, TAG, "parse URI"); unsigned char portbuf[2]; unsigned char _buf[CA_BUFSIZE]; unsigned char *buf = _buf; coap_uri_t uri; size_t buflen; uint32_t res; OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo); /* split arg into Uri-* options */ coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri); if (uri.port != COAP_DEFAULT_PORT) { coap_insert(optlist, CACreateNewOptionNode(COAP_OPTION_URI_PORT, coap_encode_var_bytes(portbuf, uri.port), portbuf), CAOrderOpts); } if (uri.path.length) { buflen = CA_BUFSIZE; res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); while (res--) { coap_insert(optlist, CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)), CAOrderOpts); buf += COAP_OPT_SIZE(buf); } } if (uri.query.length) { buflen = CA_BUFSIZE; buf = _buf; res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); while (res--) { coap_insert(optlist, CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)), CAOrderOpts); buf += COAP_OPT_SIZE(buf); } } }
void check_async(coap_context_t *ctx, coap_tick_t now) { coap_pdu_t *response; coap_async_state_t *tmp; unsigned char buf[2]; size_t size = sizeof(coap_hdr_t) + 8; if (!async || now < async->created + (unsigned long)async->appdata) return; size += async->tokenlen; 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"); async->appdata = (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND); return; } response->hdr->id = coap_new_message_id(ctx); if (async->tokenlen) coap_add_token(response, async->tokenlen, async->token); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); 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->hdr->id); } coap_delete_pdu(response); coap_remove_async(ctx, async->id, &tmp); coap_free_async(async); async = NULL; }
void hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response, void *userdata) { rd_t *rd = NULL; unsigned char buf[3]; HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); if (rd && rd->etag_len) coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag); if (rd && rd->data.s) coap_add_data(response, rd->data.length, rd->data.s); }
void hnd_get_query(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { coap_opt_iterator_t opt_iter; coap_opt_filter_t f; coap_opt_t *q; size_t len, L; unsigned char buf[70]; (void)ctx; (void)resource; (void)peer; (void)token; response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); coap_option_filter_clear(f); coap_option_setb(f, COAP_OPTION_URI_QUERY); coap_option_iterator_init(request, &opt_iter, f); len = 0; while ((len < sizeof(buf)) && (q = coap_option_next(&opt_iter))) { L = min(sizeof(buf) - len, 11); memcpy(buf + len, "Uri-Query: ", L); len += L; L = min(sizeof(buf) - len, COAP_OPT_LENGTH(q)); memcpy(buf + len, COAP_OPT_VALUE(q), L); len += L; if (len < sizeof(buf)) buf[len++] = '\n'; } coap_add_data(response, len, buf); }
static void send_async_response(coap_context_t *ctx, const coap_endpoint_t *local_if) { coap_pdu_t *response; unsigned char buf[3]; const char* response_data = "Hello World!"; size_t size = sizeof(coap_hdr_t) + 20; response = coap_pdu_init(async->flags & COAP_MESSAGE_CON, COAP_RESPONSE_CODE(205), 0, size); response->hdr->id = coap_new_message_id(ctx); if (async->tokenlen) coap_add_token(response, async->tokenlen, async->token); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); coap_add_data (response, strlen(response_data), (unsigned char *)response_data); if (coap_send(ctx, local_if, &async->peer, response) == COAP_INVALID_TID) { } coap_delete_pdu(response); coap_async_state_t *tmp; coap_remove_async(ctx, async->id, &tmp); coap_free_async(async); async = NULL; }
CAResult_t CAParseHeadOption(uint32_t code, const CAInfo_t *info, coap_list_t **optlist) { (void)code; OIC_LOG(DEBUG, TAG, "IN"); VERIFY_NON_NULL_RET(info, TAG, "info is NULL", CA_STATUS_INVALID_PARAM); OIC_LOG_V(DEBUG, TAG, "parse Head Opt: %d", info->numOptions); if (!optlist) { OIC_LOG(ERROR, TAG, "optlist is null"); return CA_STATUS_INVALID_PARAM; } for (uint32_t i = 0; i < info->numOptions; i++) { if(!(info->options + i)) { OIC_LOG(ERROR, TAG, "options is not available"); return CA_STATUS_FAILED; } uint32_t id = (info->options + i)->optionID; if (COAP_OPTION_URI_PATH == id || COAP_OPTION_URI_QUERY == id) { OIC_LOG_V(DEBUG, TAG, "not Header Opt: %d", id); } else { if ((info->options + i)->optionData && (info->options + i)->optionLength > 0) { OIC_LOG_V(DEBUG, TAG, "Head opt ID: %d", id); OIC_LOG_V(DEBUG, TAG, "Head opt data: %s", (info->options + i)->optionData); OIC_LOG_V(DEBUG, TAG, "Head opt length: %d", (info->options + i)->optionLength); int ret = coap_insert(optlist, CACreateNewOptionNode(id, (info->options + i)->optionLength, (info->options + i)->optionData), CAOrderOpts); if (ret <= 0) { return CA_STATUS_INVALID_PARAM; } } } } // insert one extra header with the payload format if applicable. if (CA_FORMAT_UNDEFINED != info->payloadFormat) { coap_list_t* node = NULL; uint8_t buf[3] = {0}; switch (info->payloadFormat) { case CA_FORMAT_CBOR: node = CACreateNewOptionNode( COAP_OPTION_CONTENT_FORMAT, coap_encode_var_bytes(buf, (uint16_t)COAP_MEDIATYPE_APPLICATION_CBOR), (char *)buf); break; default: OIC_LOG_V(ERROR, TAG, "format option:[%d] not supported", info->payloadFormat); } if (!node) { OIC_LOG(ERROR, TAG, "format option not created"); return CA_STATUS_INVALID_PARAM; } int ret = coap_insert(optlist, node, CAOrderOpts); if (ret <= 0) { coap_delete(node); OIC_LOG(ERROR, TAG, "format option not inserted in header"); return CA_STATUS_INVALID_PARAM; } } OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; }
CAResult_t CAParseURI(const char *uriInfo, coap_list_t **optlist) { OIC_LOG(DEBUG, TAG, "IN"); if (NULL == uriInfo) { OIC_LOG(ERROR, TAG, "uriInfo is null"); return CA_STATUS_INVALID_PARAM; } OIC_LOG_V(DEBUG, TAG, "url : %s", uriInfo); if (NULL == optlist) { OIC_LOG(ERROR, TAG, "optlist is null"); return CA_STATUS_INVALID_PARAM; } /* split arg into Uri-* options */ coap_uri_t uri; coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri); if (uri.port != COAP_DEFAULT_PORT) { unsigned char portbuf[CA_PORT_BUFFER_SIZE] = { 0 }; int ret = coap_insert(optlist, CACreateNewOptionNode(COAP_OPTION_URI_PORT, coap_encode_var_bytes(portbuf, uri.port), (char *)portbuf), CAOrderOpts); if (ret <= 0) { return CA_STATUS_INVALID_PARAM; } } if (uri.path.s && uri.path.length) { CAResult_t ret = CAParseUriPartial(uri.path.s, uri.path.length, COAP_OPTION_URI_PATH, optlist); if (CA_STATUS_OK != ret) { OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri path)"); return ret; } } if (uri.query.s && uri.query.length) { CAResult_t ret = CAParseUriPartial(uri.query.s, uri.query.length, COAP_OPTION_URI_QUERY, optlist); if (CA_STATUS_OK != ret) { OIC_LOG(ERROR, TAG, "CAParseUriPartial failed(uri query)"); return ret; } } OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; }
const coap_endpoint_t *local_interface UNUSED_PARAM, coap_address_t *peer UNUSED_PARAM, coap_pdu_t *request UNUSED_PARAM, str *token UNUSED_PARAM, coap_pdu_t *response) { unsigned char buf[3]; response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX); } static void hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource, const coap_endpoint_t *local_interface UNUSED_PARAM, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { coap_opt_iterator_t opt_iter; coap_opt_t *option; unsigned char buf[40];
void hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { coap_key_t etag; unsigned char buf[2]; coap_payload_t *test_payload; coap_block_t block; (void)ctx; (void)peer; (void)token; test_payload = coap_find_payload(resource->key); if (!test_payload) { response->hdr->code = COAP_RESPONSE_CODE(500); return; } response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, test_payload->media_type), buf); /* add etag for the resource */ if (test_payload->flags & REQUIRE_ETAG) { memset(etag, 0, sizeof(etag)); coap_hash(test_payload->data, test_payload->length, etag); coap_add_option(response, COAP_OPTION_ETAG, sizeof(etag), etag); } if (request) { int res; if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) { res = coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response, test_payload->length); switch (res) { case -2: /* illegal block */ response->hdr->code = COAP_RESPONSE_CODE(400); goto error; case -1: /* should really not happen */ assert(0); /* fall through if assert is a no-op */ case -3: /* cannot handle request */ response->hdr->code = COAP_RESPONSE_CODE(500); goto error; default: /* everything is good */ ; } coap_add_block(response, test_payload->length, test_payload->data, block.num, block.szx); } else { if (!coap_add_data(response, test_payload->length, test_payload->data)) { /* set initial block size, will be lowered by * coap_write_block_opt) automatically */ block.szx = 6; coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response, test_payload->length); coap_add_block(response, test_payload->length, test_payload->data, block.num, block.szx); } } } else { /* this is a notification, block is 0 */ /* FIXME: need to store block size with subscription */ } return; error: coap_add_data(response, strlen(coap_response_phrase(response->hdr->code)), (unsigned char *)coap_response_phrase(response->hdr->code)); }
void hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { coap_opt_iterator_t opt_iter; coap_opt_t *option; unsigned char buf[40]; size_t len; time_t now; coap_tick_t t; coap_subscription_t *subscription; /* 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 */ response->hdr->code = my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); if (request != NULL && coap_check_option(request, COAP_OPTION_OBSERVE, &opt_iter)) { subscription = coap_add_observer(resource, peer, token); if (subscription) { subscription->non = request->hdr->type == COAP_MESSAGE_NON; coap_add_option(response, COAP_OPTION_OBSERVE, 0, NULL); } } if (resource->dirty == 1) coap_add_option(response, COAP_OPTION_OBSERVE, coap_encode_var_bytes(buf, ctx->observe), buf); if (my_clock_base) coap_add_option(response, COAP_OPTION_CONTENT_FORMAT, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x01), buf); if (my_clock_base) { /* calculate current time */ 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)) && 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); coap_add_data(response, len, buf); } else { /* output human-readable time */ struct tm *tmp; tmp = gmtime(&now); len = strftime((char *)buf, min(sizeof(buf), response->max_size - response->length), "%b %d %H:%M:%S", tmp); coap_add_data(response, len, buf); } } }
void CoAPRDLookUpEPResource::handler_get(CoAPCallback &callback) { std::string ep_result; find_ep_result(ep_result); if (ep_result.empty()) { coap_pdu_t *response = (coap_pdu_t*)callback.response_; /* create response */ response->hdr->code = COAP_RESPONSE_404; } else { unsigned char buf[3]; std::string result; coap_block_t block_opt; coap_pdu_t *response = (coap_pdu_t*)callback.response_; /* create response */ response->hdr->code = COAP_RESPONSE_CODE(205); coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf); /* 1.if result more than 1024 byte, block wise transfer, * otherwise directly transfer * 2. if client set block2 option, response must be block-wise transferred */ if (1 == coap_get_block((coap_pdu_t*)callback.request_, COAP_OPTION_BLOCK2, &block_opt)) { ACE_DEBUG((LM_DEBUG, "send data by block from %d(size=%d)\n",block_opt.num,block_opt.szx)); if (1 == send_data_by_block(response, &block_opt, (unsigned char*)ep_result.c_str(), ep_result.length())) { return; } } if (ep_result.length() > 1024 ) { block_opt.szx = 6; block_opt.m = 1; block_opt.num = 0; ACE_DEBUG((LM_DEBUG, "send data by block from %d(size=%d)\n",block_opt.num,block_opt.szx)); if (1 == send_data_by_block(response, &block_opt, (unsigned char*)ep_result.c_str(), ep_result.length())) { return; } } /* at here, we send data directly*/ { ACE_DEBUG((LM_DEBUG, "send data directly(len=%d)\n", ep_result.length())); coap_add_data(response, ep_result.length(), (unsigned char*)ep_result.c_str()); } } }