Example #1
0
coap_opt_t *
coap_check_option(coap_pdu_t *pdu, unsigned char type, 
		  coap_opt_iterator_t *oi) {
  coap_opt_filter_t f;
  
  memset(f, 0, sizeof(coap_opt_filter_t));
  coap_option_setb(f, type);

  coap_option_iterator_init(pdu, oi, f);

  coap_option_next(oi);

  return oi->option && oi->type == type ? oi->option : NULL;
}
Example #2
0
/* 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));
}
uint32_t CAGetOptionCount(coap_opt_iterator_t opt_iter)
{
    OIC_LOG(DEBUG, TAG, "IN");
    uint32_t count = 0;
    coap_opt_t *option;

    while ((option = coap_option_next(&opt_iter)))
    {
        if (COAP_OPTION_URI_PATH != opt_iter.type && COAP_OPTION_URI_QUERY != opt_iter.type
                && COAP_OPTION_BLOCK1 != opt_iter.type && COAP_OPTION_BLOCK2 != opt_iter.type
                && COAP_OPTION_SIZE1 != opt_iter.type && COAP_OPTION_SIZE2 != opt_iter.type
                && COAP_OPTION_CONTENT_FORMAT != opt_iter.type)
        {
            count++;
        }
    }

    OIC_LOG(DEBUG, TAG, "OUT");
    return count;
}
Example #4
0
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);
}
Example #5
0
// 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 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);
    }
}