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 CoAP_RD_Resource::response_ok(CoAPResource *node, CoAPCallback &callback) { #define LOCSIZE 68 coap_pdu_t *response = (coap_pdu_t*)callback.response_; /* create response */ response->hdr->code = COAP_RESPONSE_CODE(201); { /* split path into segments and add Location-Path options */ unsigned char _b[LOCSIZE]; unsigned char *b = _b; size_t buflen = sizeof(_b); int nseg; nseg = coap_split_path((unsigned char*)node->uri().c_str(), node->uri().length(), b, &buflen); while (nseg--) { coap_add_option(response, COAP_OPTION_LOCATION_PATH, COAP_OPT_LENGTH(b), COAP_OPT_VALUE(b)); b += COAP_OPT_SIZE(b); } } }
void hnd_get_async(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 long delay = 5; size_t size; if (async) { if (async->id != request->hdr->id) { coap_opt_filter_t f; coap_option_filter_clear(f); response->hdr->code = COAP_RESPONSE_CODE(503); } return; } option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); if (option) { unsigned char *p = COAP_OPT_VALUE(option); delay = 0; for (size = COAP_OPT_LENGTH(option); size; --size, ++p) delay = delay * 10 + (*p - '0'); } async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, (void *)(COAP_TICKS_PER_SECOND * delay)); }
rd_t * make_rd(coap_address_t *peer, coap_pdu_t *pdu) { rd_t *rd; unsigned char *data; coap_opt_iterator_t opt_iter; coap_opt_t *etag; rd = rd_new(); if (!rd) { debug("hnd_get_rd: cannot allocate storage for rd\n"); return NULL; } if (coap_get_data(pdu, &rd->data.length, &data)) { rd->data.s = (unsigned char *)coap_malloc(rd->data.length); if (!rd->data.s) { debug("hnd_get_rd: cannot allocate storage for rd->data\n"); rd_delete(rd); return NULL; } memcpy(rd->data.s, data, rd->data.length); } etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter); if (etag) { rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); } return rd; }
/* handler for TD_COAP_CORE_16 */ void hnd_get_separate(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; coap_opt_filter_t f; unsigned long delay = 5; (void)resource; (void)token; if (async) { if (async->id != request->hdr->id) { coap_opt_filter_t f; coap_option_filter_clear(f); response->hdr->code = COAP_RESPONSE_CODE(503); } return; } /* search for option delay in query list */ coap_option_filter_clear(f); coap_option_setb(f, COAP_OPTION_URI_QUERY); coap_option_iterator_init(request, &opt_iter, f); while ((option = coap_option_next(&opt_iter))) { if (strncmp("delay=", (char *)COAP_OPT_VALUE(option), 6) == 0) { int i; unsigned long d = 0; for (i = 6; i < COAP_OPT_LENGTH(option); ++i) d = d * 10 + COAP_OPT_VALUE(option)[i] - '0'; /* don't allow delay to be less than COAP_RESOURCE_CHECK_TIME*/ delay = d < COAP_RESOURCE_CHECK_TIME_SEC ? COAP_RESOURCE_CHECK_TIME_SEC : d; debug("set delay to %lu\n", delay); break; } } async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE, (void *)(COAP_TICKS_PER_SECOND * delay)); }
CAResult_t CAParseUriPartial(const unsigned char *str, size_t length, int target, coap_list_t **optlist) { if (!optlist) { OIC_LOG(ERROR, TAG, "optlist is null"); return CA_STATUS_INVALID_PARAM; } if ((target != COAP_OPTION_URI_PATH) && (target != COAP_OPTION_URI_QUERY)) { // should never occur. Log just in case. OIC_LOG(DEBUG, TAG, "Unexpected URI component."); return CA_NOT_SUPPORTED; } else if (str && length) { unsigned char uriBuffer[CA_BUFSIZE] = { 0 }; unsigned char *pBuf = uriBuffer; size_t buflen = sizeof(uriBuffer); int res = (target == COAP_OPTION_URI_PATH) ? coap_split_path(str, length, pBuf, &buflen) : coap_split_query(str, length, pBuf, &buflen); if (res > 0) { size_t prevIdx = 0; while (res--) { int ret = coap_insert(optlist, CACreateNewOptionNode(target, COAP_OPT_LENGTH(pBuf), (char *)COAP_OPT_VALUE(pBuf)), CAOrderOpts); if (ret <= 0) { return CA_STATUS_INVALID_PARAM; } size_t optSize = COAP_OPT_SIZE(pBuf); if ((prevIdx + optSize) < buflen) { pBuf += optSize; prevIdx += optSize; } } } else { OIC_LOG_V(ERROR, TAG, "Problem parsing URI : %d for %d", res, target); return CA_STATUS_FAILED; } } else { OIC_LOG(ERROR, TAG, "str or length is not available"); return CA_STATUS_FAILED; } return CA_STATUS_OK; }
void hnd_put_test(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; coap_payload_t *payload; size_t len; unsigned char *data; (void)ctx; (void)peer; (void)token; response->hdr->code = COAP_RESPONSE_CODE(204); coap_get_data(request, &len, &data); payload = coap_find_payload(resource->key); if (payload && payload->max_data < len) { /* need more storage */ coap_delete_payload(payload); payload = NULL; /* bug: when subsequent coap_new_payload() fails, our old contents is gone */ } if (!payload) { /* create new payload */ payload = coap_new_payload(len); if (!payload) goto error; coap_add_payload(resource->key, payload, NULL); } payload->length = len; memcpy(payload->data, data, len); option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); if (option) { /* set media type given in request */ payload->media_type = coap_decode_var_bytes(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option)); } else { /* set default value */ payload->media_type = COAP_MEDIATYPE_TEXT_PLAIN; } /* FIXME: need to change attribute ct of resource. To do so, we need dynamic management of the attribute value */ return; error: warn("cannot modify resource\n"); response->hdr->code = COAP_RESPONSE_CODE(500); }
void for_each_option(coap_pdu_t *pdu, void (*f)(coap_opt_t *, unsigned char, unsigned int, const unsigned char *) ) { unsigned char cnt; coap_opt_t *opt; unsigned char opt_code = 0; if (! pdu ) return; opt = options_start( pdu ); for ( cnt = pdu->hdr->optcnt; cnt; --cnt ) { opt_code += COAP_OPT_DELTA(*opt); f ( opt, opt_code, COAP_OPT_LENGTH(*opt), COAP_OPT_VALUE(*opt) ); opt = (coap_opt_t *)( (unsigned char *)opt + COAP_OPT_SIZE(*opt) ); } }
static void query_value(coap_pdu_t *pdu, std::string &key, std::string &value) { coap_opt_iterator_t opt_iter; coap_opt_t *query; str v = {0, NULL}; query = coap_check_option(pdu, COAP_OPTION_URI_QUERY, &opt_iter); if (query) { parse_param((unsigned char *)key.c_str(), key.length(), COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &v); } if (v.length > 0) value.assign((const char*)v.s, v.length); }
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); }
// When we receive the CoAP response we build and send the HTTP response void coap_response_handler(struct coap_context_t *ctx, const coap_endpoint_t *local_interface, const coap_address_t *remote, coap_pdu_t *sent, coap_pdu_t *received, const coap_tid_t id) { printf("COAP %13s:%-5u -> ", inet_ntoa((&remote->addr.sin)->sin_addr), ntohs((&remote->addr.sin)->sin_port)); coap_show_pdu(received); for(int i = 0; i < MAX_HTTP_CONNECTIONS; i++) { if(http_coap_pairs[i].message_id == received->hdr->id) { struct MHD_Connection *connection = http_coap_pairs[i].connection; size_t len = 0; unsigned char *databuf = NULL; struct MHD_Response *response = MHD_create_response_from_buffer(len, databuf, MHD_RESPMEM_MUST_COPY); int read_result = coap_get_data(received, &len, &databuf); if(received->hdr->code == COAP_RESPONSE_CODE(205) && read_result == 0) { coap_abort_to_http(connection, "coap_get_data: cannot read CoAP response data\n"); } static char tid_str[8]; snprintf(tid_str, sizeof(tid_str), "%u", ntohs(received->hdr->id)); MHD_add_response_header(response, "X-CoAP-Message-Id", tid_str); MHD_add_response_header(response, "X-CoAP-Response-Code", msg_code_string(received->hdr->code)); // HTTP Content-Type const char *http_content_type; int coap_content_format; coap_opt_iterator_t opt_iter; coap_opt_t *option; coap_option_iterator_init(received, &opt_iter, COAP_OPT_ALL); while((option = coap_option_next(&opt_iter))) { switch(opt_iter.type) { case COAP_OPTION_CONTENT_FORMAT: coap_content_format = (int)coap_decode_var_bytes(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option)); break; default: continue; } } switch(coap_content_format) { case COAP_MEDIATYPE_TEXT_PLAIN: http_content_type = "text/plain"; break; case COAP_MEDIATYPE_APPLICATION_LINK_FORMAT: http_content_type = "application/link-format"; break; case COAP_MEDIATYPE_APPLICATION_XML: http_content_type = "application/xml"; break; case COAP_MEDIATYPE_APPLICATION_OCTET_STREAM: http_content_type = "application/octet-stream"; break; case COAP_MEDIATYPE_APPLICATION_EXI: http_content_type = "application/exi"; break; case COAP_MEDIATYPE_APPLICATION_JSON: http_content_type = "application/json"; break; case COAP_MEDIATYPE_APPLICATION_CBOR: http_content_type = "application/cbor"; break; default: http_content_type = "unknown"; break; } MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE, http_content_type); // HTTP Code unsigned int http_code; switch(received->hdr->code) { case COAP_RESPONSE_200: http_code = MHD_HTTP_NO_CONTENT; break; /* 2.00 OK */ case COAP_RESPONSE_201: http_code = MHD_HTTP_CREATED; break; /* 2.01 Created */ case COAP_RESPONSE_CODE(205): http_code = MHD_HTTP_OK; break; case COAP_RESPONSE_304: http_code = MHD_HTTP_ACCEPTED; break; /* 2.03 Valid */ case COAP_RESPONSE_400: http_code = MHD_HTTP_BAD_REQUEST; break; /* 4.00 Bad Request */ case COAP_RESPONSE_404: http_code = MHD_HTTP_NOT_FOUND; break; /* 4.04 Not Found */ case COAP_RESPONSE_405: http_code = MHD_HTTP_NOT_ACCEPTABLE; break; /* 4.05 Method Not Allowed */ case COAP_RESPONSE_415: http_code = MHD_HTTP_UNSUPPORTED_MEDIA_TYPE;break; /* 4.15 Unsupported Media Type */ case COAP_RESPONSE_500: http_code = MHD_HTTP_INTERNAL_SERVER_ERROR; break; /* 5.00 Internal Server Error */ case COAP_RESPONSE_501: http_code = MHD_HTTP_NOT_IMPLEMENTED; break; /* 5.01 Not Implemented */ case COAP_RESPONSE_503: http_code = MHD_HTTP_SERVICE_UNAVAILABLE; break; /* 5.03 Service Unavailable */ case COAP_RESPONSE_504: http_code = MHD_HTTP_GATEWAY_TIMEOUT; break; /* 5.04 Gateway Timeout */ default: http_code = MHD_HTTP_INTERNAL_SERVER_ERROR; break; } // Send the response MHD_queue_response(connection, http_code, response); MHD_destroy_response(response); const struct sockaddr_in *client_addr = (const struct sockaddr_in *) MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS)->client_addr; printf("HTTP %13s:%-5u <- %u %s [ %s, %zu bytes, \"%s\" ]\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port), http_code, http_reason_phrase_for(http_code), http_content_type, len, (databuf != NULL) ? (char *)databuf : ""); } // clear the association http_coap_pairs[i].connection = NULL; return; } }
CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo) { OIC_LOG(DEBUG, TAG, "IN"); if (!pdu || !outCode || !outInfo) { OIC_LOG(ERROR, TAG, "NULL pointer param"); return CA_STATUS_INVALID_PARAM; } coap_opt_iterator_t opt_iter; coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL); if (outCode) { (*outCode) = (uint32_t) CA_RESPONSE_CODE(pdu->hdr->code); } // init HeaderOption list uint32_t count = CAGetOptionCount(opt_iter); memset(outInfo, 0, sizeof(*outInfo)); outInfo->numOptions = count; // set type outInfo->type = pdu->hdr->type; // set message id outInfo->messageId = pdu->hdr->id; outInfo->payloadFormat = CA_FORMAT_UNDEFINED; if (count > 0) { outInfo->options = (CAHeaderOption_t *) OICCalloc(count, sizeof(CAHeaderOption_t)); if (NULL == outInfo->options) { OIC_LOG(ERROR, TAG, "Out of memory"); return CA_MEMORY_ALLOC_FAILED; } } coap_opt_t *option; char optionResult[CA_MAX_URI_LENGTH] = {0}; uint32_t idx = 0; uint32_t optionLength = 0; bool isfirstsetflag = false; bool isQueryBeingProcessed = false; while ((option = coap_option_next(&opt_iter))) { char buf[COAP_MAX_PDU_SIZE] = {0}; uint32_t bufLength = CAGetOptionData(opt_iter.type, (uint8_t *)(COAP_OPT_VALUE(option)), COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf)); if (bufLength) { OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf); if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type) { if (false == isfirstsetflag) { isfirstsetflag = true; optionResult[optionLength] = '/'; optionLength++; // Make sure there is enough room in the optionResult buffer if ((optionLength + bufLength) < sizeof(optionResult)) { memcpy(&optionResult[optionLength], buf, bufLength); optionLength += bufLength; } else { goto exit; } } else { if (COAP_OPTION_URI_PATH == opt_iter.type) { // Make sure there is enough room in the optionResult buffer if (optionLength < sizeof(optionResult)) { optionResult[optionLength] = '/'; optionLength++; } else { goto exit; } } else if (COAP_OPTION_URI_QUERY == opt_iter.type) { if (false == isQueryBeingProcessed) { // Make sure there is enough room in the optionResult buffer if (optionLength < sizeof(optionResult)) { optionResult[optionLength] = '?'; optionLength++; isQueryBeingProcessed = true; } else { goto exit; } } else { // Make sure there is enough room in the optionResult buffer if (optionLength < sizeof(optionResult)) { optionResult[optionLength] = ';'; optionLength++; } else { goto exit; } } } // Make sure there is enough room in the optionResult buffer if ((optionLength + bufLength) < sizeof(optionResult)) { memcpy(&optionResult[optionLength], buf, bufLength); optionLength += bufLength; } else { goto exit; } } } else if (COAP_OPTION_BLOCK1 == opt_iter.type || COAP_OPTION_BLOCK2 == opt_iter.type || COAP_OPTION_SIZE1 == opt_iter.type || COAP_OPTION_SIZE2 == opt_iter.type) { OIC_LOG_V(DEBUG, TAG, "option[%d] will be filtering", opt_iter.type); } else if (COAP_OPTION_CONTENT_FORMAT == opt_iter.type) { if (1 == COAP_OPT_LENGTH(option) && COAP_MEDIATYPE_APPLICATION_CBOR == buf[0]) { outInfo->payloadFormat = CA_FORMAT_CBOR; } else { outInfo->payloadFormat = CA_FORMAT_UNSUPPORTED; } OIC_LOG_V(DEBUG, TAG, "option[%d] has format [%d]", opt_iter.type, (uint8_t)buf[0]); } else { if (idx < count) { uint32_t length = bufLength; if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH) { outInfo->options[idx].optionID = opt_iter.type; outInfo->options[idx].optionLength = length; outInfo->options[idx].protocolID = CA_COAP_ID; memcpy(outInfo->options[idx].optionData, buf, length); idx++; } } } } } // set token data if (pdu->hdr->token_length > 0) { OIC_LOG_V(DEBUG, TAG, "inside token length : %d", pdu->hdr->token_length); outInfo->token = (char *) OICMalloc(pdu->hdr->token_length); if (NULL == outInfo->token) { OIC_LOG(ERROR, TAG, "Out of memory"); OICFree(outInfo->options); return CA_MEMORY_ALLOC_FAILED; } memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length); } outInfo->tokenLength = pdu->hdr->token_length; // set payload data size_t dataSize; uint8_t *data; if (coap_get_data(pdu, &dataSize, &data)) { OIC_LOG(DEBUG, TAG, "inside pdu->data"); outInfo->payload = (uint8_t *) OICMalloc(dataSize); if (NULL == outInfo->payload) { OIC_LOG(ERROR, TAG, "Out of memory"); OICFree(outInfo->options); OICFree(outInfo->token); return CA_MEMORY_ALLOC_FAILED; } memcpy(outInfo->payload, pdu->data, dataSize); outInfo->payloadSize = dataSize; } if (optionResult[0] != '\0') { OIC_LOG_V(DEBUG, TAG, "URL length:%d", strlen(optionResult)); outInfo->resourceUri = OICStrdup(optionResult); if (!outInfo->resourceUri) { OIC_LOG(ERROR, TAG, "Out of memory"); OICFree(outInfo->options); OICFree(outInfo->token); return CA_MEMORY_ALLOC_FAILED; } } OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; exit: OIC_LOG(ERROR, TAG, "buffer too small"); OICFree(outInfo->options); return CA_STATUS_FAILED; }
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 CAGetRequestPDUInfo(const coap_pdu_t *pdu, uint32_t* outCode, CAInfo_t* outInfo) { unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */ uint32_t encode = 0; coap_opt_iterator_t opt_iter; coap_opt_t *option; char optionResult[CA_URI_MAX_SIZE] = { 0, }; uint32_t count = 0; uint32_t isfirstsetflag = 0; /* show options, if any */ coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL); memset(optionResult, 0, sizeof(optionResult)); while ((option = coap_option_next(&opt_iter))) { if (print_readable(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), buf, sizeof(buf), encode)) { if (opt_iter.type == COAP_OPTION_URI_PATH || opt_iter.type == COAP_OPTION_URI_QUERY) { if (0 == isfirstsetflag) { isfirstsetflag = 1; memcpy(optionResult + count, buf, strlen(buf)); count += strlen(buf); } else { if (opt_iter.type == COAP_OPTION_URI_PATH) { memcpy(optionResult + count, "/", 1); count++; } else if (opt_iter.type == COAP_OPTION_URI_QUERY) { memcpy(optionResult + count, "?", 1); count++; } memcpy(optionResult + count, buf, strlen(buf)); count += strlen(buf); } } } } OIC_LOG(DEBUG, TAG, "set CAInfo_t after parsing"); // set pdu info (*outCode) = (uint32_t) pdu->hdr->code; memset(outInfo, 0, sizeof(CAInfo_t)); outInfo->options = (CAHeaderOption_t*) OICMalloc(sizeof(CAHeaderOption_t)); memset(outInfo->options, 0, sizeof(CAHeaderOption_t)); outInfo->options->optionID = opt_iter.type; outInfo->options->optionLength = count; memcpy(outInfo->options->optionData, optionResult, CA_MAX_HEADER_OPTION_DATA_LENGTH); if (pdu->hdr->token_length > 0) { outInfo->token = (char*) OICMalloc(pdu->hdr->token_length); memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length); } if (NULL != pdu->data) { outInfo->payload = (char*) OICMalloc(strlen(pdu->data) + 1); memcpy(outInfo->payload, pdu->data, strlen(pdu->data) + 1); } }
void hnd_put_resource(coap_context_t *ctx, struct coap_resource_t *resource, const coap_endpoint_t *local_interface, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { #if 1 response->hdr->code = COAP_RESPONSE_CODE(501); #else /* FIXME */ coap_opt_iterator_t opt_iter; coap_opt_t *token, *etag; coap_pdu_t *response; size_t size = sizeof(coap_hdr_t); int type = (request->hdr->type == COAP_MESSAGE_CON) ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; rd_t *rd = NULL; unsigned char code; /* result code */ unsigned char *data; str tmp; HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd); if (rd) { /* found resource object, now check Etag */ etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter); if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len) || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) { if (coap_get_data(request, &tmp.length, &data)) { tmp.s = (unsigned char *)coap_malloc(tmp.length); if (!tmp.s) { debug("hnd_put_rd: cannot allocate storage for new rd\n"); code = COAP_RESPONSE_CODE(503); goto finish; } coap_free(rd->data.s); rd->data.s = tmp.s; rd->data.length = tmp.length; memcpy(rd->data.s, data, rd->data.length); } } if (etag) { rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag)); memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len); } code = COAP_RESPONSE_CODE(204); /* FIXME: update lifetime */ } else { code = COAP_RESPONSE_CODE(503); } finish: /* FIXME: do not create a new response but use the old one instead */ response = coap_pdu_init(type, code, request->hdr->id, size); if (!response) { debug("cannot create response for message %d\n", request->hdr->id); return; } if (request->hdr->token_length) coap_add_token(response, request->hdr->token_length, request->hdr->token); if (coap_send(ctx, peer, response) == COAP_INVALID_TID) { debug("hnd_get_rd: cannot send response for message %d\n", request->hdr->id); } coap_delete_pdu(response); #endif }
void hnd_post_test(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; coap_payload_t *test_payload; size_t len; size_t l = 6 + sizeof(void *); coap_dynamic_uri_t *uri; unsigned char *data; #define BUFSIZE 20 int res; unsigned char _buf[BUFSIZE]; unsigned char *buf = _buf; size_t buflen = BUFSIZE; (void)resource; (void)peer; (void)token; coap_get_data(request, &len, &data); /* allocate storage for resource and to hold URI */ test_payload = coap_new_payload(len); uri = (coap_dynamic_uri_t *)coap_malloc(sizeof(coap_dynamic_uri_t) + l); if (!(test_payload && uri)) { coap_log(LOG_CRIT, "cannot allocate new resource under /test"); response->hdr->code = COAP_RESPONSE_CODE(500); coap_free(test_payload); coap_free(uri); } else { coap_resource_t *r; memset(uri, 0, sizeof(coap_dynamic_uri_t)); uri->length = min(l, (size_t)snprintf((char *)uri->data, l, "test/%p", (void*)test_payload)); test_payload->length = len; memcpy(test_payload->data, data, len); r = coap_resource_init(uri->data, uri->length, 0); coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); /* set media_type if available */ option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter); if (option) { test_payload->media_type = coap_decode_var_bytes(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option)); } coap_add_resource(ctx, r); coap_add_payload(r->key, test_payload, uri); /* add Location-Path */ res = coap_split_path(uri->data, uri->length, buf, &buflen); while (res--) { coap_add_option(response, COAP_OPTION_LOCATION_PATH, COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)); buf += COAP_OPT_SIZE(buf); } response->hdr->code = COAP_RESPONSE_CODE(201); } }
void hnd_post_rd(coap_context_t *ctx, struct coap_resource_t *resource, const coap_endpoint_t *local_interface, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { size_t len=0; unsigned char *databuf; unsigned char strBuf[100]; unsigned char s[100]; coap_print_addr(peer, s, 100); if (coap_get_data(request, &len, &databuf)){ memcpy(strBuf, databuf, len); strBuf[len]='\0'; fprintf(stdout, "%s %s\n", s, strBuf); }else{ fprintf(stdout, "%s\n", s); } fflush(stdout); coap_resource_t *r; coap_opt_iterator_t opt_iter; coap_opt_t *query; #define LOCSIZE 68 unsigned char *loc; size_t loc_size; str h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */ unsigned char *buf; loc = (unsigned char *)coap_malloc(LOCSIZE); if (!loc) { response->hdr->code = COAP_RESPONSE_CODE(500); return; } memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); loc_size = RD_ROOT_SIZE; loc[loc_size++] = '/'; /* store query parameters for later use */ query = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); if (query) { parse_param((unsigned char *)"h", 1, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &h); parse_param((unsigned char *)"ins", 3, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &ins); parse_param((unsigned char *)"lt", 2, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), <); parse_param((unsigned char *)"rt", 2, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &rt); } if (h.length) { /* client has specified a node name */ memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); loc_size += min(h.length, LOCSIZE - loc_size - 1); if (ins.length && loc_size > 1) { loc[loc_size++] = '-'; memcpy((char *)(loc + loc_size), ins.s, min(ins.length, LOCSIZE - loc_size - 1)); loc_size += min(ins.length, LOCSIZE - loc_size - 1); } } else { /* generate node identifier */ loc_size += snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, "%x", request->hdr->id); if (loc_size > 1) { if (ins.length) { loc[loc_size++] = '-'; memcpy((char *)(loc + loc_size), ins.s, min(ins.length, LOCSIZE - loc_size - 1)); loc_size += min(ins.length, LOCSIZE - loc_size - 1); } else { coap_tick_t now; coap_ticks(&now); loc_size += snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, "-%x", now); } } } /* TODO: * - use lt to check expiration */ r = coap_resource_init(loc, loc_size, COAP_RESOURCE_FLAGS_RELEASE_URI); coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_resource); coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); if (ins.s) { buf = (unsigned char *)coap_malloc(ins.length + 2); if (buf) { /* add missing quotes */ buf[0] = '"'; memcpy(buf + 1, ins.s, ins.length); buf[ins.length + 1] = '"'; coap_add_attr(r, (unsigned char *)"ins", 3, buf, ins.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE); } } if (rt.s) { buf = (unsigned char *)coap_malloc(rt.length + 2); if (buf) { /* add missing quotes */ buf[0] = '"'; memcpy(buf + 1, rt.s, rt.length); buf[rt.length + 1] = '"'; coap_add_attr(r, (unsigned char *)"rt", 2, buf, rt.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE); } } add_source_address(r, peer); { rd_t *rd; rd = make_rd(peer, request); if (rd) { coap_hash_path(loc, loc_size, rd->key); HASH_ADD(hh, resources, key, sizeof(coap_key_t), rd); } else { /* FIXME: send error response and delete r */ } } coap_add_resource(ctx, r); /* create response */ response->hdr->code = COAP_RESPONSE_CODE(201); { /* split path into segments and add Location-Path options */ unsigned char _b[LOCSIZE]; unsigned char *b = _b; size_t buflen = sizeof(_b); int nseg; nseg = coap_split_path(loc, loc_size, b, &buflen); while (nseg--) { coap_add_option(response, COAP_OPTION_LOCATION_PATH, COAP_OPT_LENGTH(b), COAP_OPT_VALUE(b)); b += COAP_OPT_SIZE(b); } } }