void coap_SendNotify(AddressType * addr, const char * path, const char * token, int tokenSize, ContentType contentType,
        const char * payload, int payloadLen, int sequence)
{
    // TODO - FIXME: if path is not full uri then map addr to Network address + append path(?)
    coap_packet_t notify;
    coap_transaction_t *transaction;
    NetworkAddress * remoteAddress = NetworkAddress_New(path, strlen(path));

    Lwm2m_Debug("Coap notify: %s\n", path);
    //Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(&addr->Addr));
    //Lwm2m_Debug("Coap request port: %d\n", addr->Port);

    coap_init_message(&notify, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());

    if (contentType != ContentType_None)
    {
        coap_set_header_content_format(&notify, contentType);
        coap_set_payload(&notify, payload, payloadLen);
    }

    coap_set_token(&notify, token, tokenSize);
    coap_set_header_observe(&notify, sequence);

    if ((transaction = coap_new_transaction(networkSocket, notify.mid, remoteAddress)))
    {
        transaction->packet_len = coap_serialize_message(&notify, transaction->packet);

        coap_send_transaction(transaction); // for NON confirmable messages this will call coap_clear_transaction();
    }
}
void coap_SendNotify(AddressType * addr, const char * path, const char * token, int tokenSize, ContentType contentType, const char * payload, int payloadLen, int sequence)
{
    coap_packet_t notify;
    coap_transaction_t *transaction;

    Lwm2m_Debug("Coap notify: %s\n", path);
    Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(&addr->Addr));
    Lwm2m_Debug("Coap request port: %d\n", addr->Port);

    coap_init_message(&notify, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());

    if (contentType != ContentType_None)
    {
        coap_set_header_content_format(&notify, contentType);
        coap_set_payload(&notify, payload, payloadLen);
    }

    coap_set_token(&notify, token, tokenSize);
    coap_set_header_observe(&notify, sequence);

    if ((transaction = coap_new_transaction(notify.mid, &addr->Addr, uip_htons(addr->Port))))
    {
        transaction->packet_len = coap_serialize_message(&notify, transaction->packet);

        coap_send_transaction(transaction); // for NON confirmable messages this will call coap_clear_transaction();
    }
}
示例#3
0
void coap_pretty_print(coap_pdu *pdu)
{
  coap_option opt;

  opt.num = 0;

  if (coap_validate_pkt(pdu) == CE_NONE){
      printf(" ------ Valid CoAP Packet (%zi) ------ \n", pdu->len);
      printf("Type:  %i\n",coap_get_type(pdu));
      printf("Code:  %i.%02i\n", coap_get_code_class(pdu), coap_get_code_detail(pdu));
      printf("MID:   0x%X\n", coap_get_mid(pdu));
      printf("Token: 0x%llX\n", coap_get_token(pdu));

      while ((opt = coap_get_option(pdu, &opt)).num != 0){
        if (opt.num == 0)
          break;

        printf("Option: %i\n", opt.num);
        if (opt.val != NULL && opt.len != 0)
          printf(" Value: %.*s (%zi)\n", (int)opt.len, opt.val, opt.len);
      }
      // Note: get_option returns payload pointer when it finds the payload marker
      if (opt.val != NULL && opt.len != 0)
        printf("Payload: %.*s (%zi)\n", (int)opt.len, opt.val, opt.len);
    } else {
      printf(" ------ Non-CoAP Message (%zi) ------ \n", pdu->len);
      hex_dump(pdu->buf, pdu->len);
    }
}
void coap_createCoapRequest(void * context, coap_method_t method, const char * uri, ContentType contentType, const char * payload, int payloadLen, TransactionCallback callback)
{
    coap_packet_t request;
    uip_ipaddr_t * remote_ipaddr = coap_getIpFromURI(uri);
    int remote_port = coap_getPortFromURI(uri);
    coap_transaction_t *transaction;
    char path[128] = {0};
    char query[128] = {0};

    coap_getPathQueryFromURI(uri, path, query);

    Lwm2m_Debug("Coap request: %s\n", uri);
    Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(remote_ipaddr));
    Lwm2m_Debug("Coap request port: %d\n", remote_port);
    Lwm2m_Debug("Coap request path: %s\n", path);
    Lwm2m_Debug("Coap request query: %s\n", query);

    coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid());

    coap_set_header_uri_path(&request, path);
    coap_set_header_uri_query(&request, query);

    if (contentType != ContentType_None)
    {
        coap_set_header_content_format(&request, contentType);
        coap_set_payload(&request, payload, payloadLen);
    }

    if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr)
    {
        Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_clear_transaction(CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
    }

    if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port))))
    {
        transaction->callback = coap_CoapRequestCallback;
        CurrentTransaction[CurrentTransactionIndex].Callback = callback;
        CurrentTransaction[CurrentTransactionIndex].Context = context;
        CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true;
        CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction;
        memcpy(&CurrentTransaction[CurrentTransactionIndex].Address.Addr, remote_ipaddr, sizeof(uip_ipaddr_t));
        CurrentTransaction[CurrentTransactionIndex].Address.Port = uip_htons(remote_port);

        transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex];

        transaction->packet_len = coap_serialize_message(&request, transaction->packet);

        Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_send_transaction(transaction);

        CurrentTransactionIndex++;

        if(CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS)
        {
            CurrentTransactionIndex = 0;
        }
    }
}
示例#5
0
文件: tres-node.c 项目: npowern/pyot
/*----------------------------------------------------------------------------*/
PROCESS_THREAD(tres_process, ev, data)
{
    PROCESS_BEGIN();

    srand(node_id);
    rest_init_engine();
    tres_init();
    rest_activate_resource(&actuator, "actuator");
    rplinfo_activate_resources();
    sprintf(setpoint, "0");
#if PYOT_KEEPALIVE
    static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */
    SERVER_NODE(&server_ipaddr);

    int wait_time = (unsigned int)(rand() % MAX_WAITING);
    int base_wait = BASE_WAITING;

    static int g_time=0;
    static char content[12];
    etimer_set(&et, (wait_time + base_wait) * CLOCK_SECOND);

    while(1) {
        PROCESS_YIELD();
        //PROCESS_WAIT_EVENT();
        if (etimer_expired(&et)) break;
    }
    etimer_reset(&et);
    etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND);

    while(1) {
        PROCESS_YIELD();
        if (etimer_expired(&et)) {

            coap_init_message(request, COAP_TYPE_NON, COAP_POST, 0 );
            coap_set_header_uri_path(request, "/rd");
            coap_set_payload(request, content, snprintf(content, sizeof(content), "%d", g_time++));
            //PRINT6ADDR(&server_ipaddr);
            //PRINTF(" : %u\n", UIP_HTONS(REMOTE_PORT));

            coap_transaction_t *transaction;

            request->mid = coap_get_mid();
            if ((transaction = coap_new_transaction(request->mid, &server_ipaddr, REMOTE_PORT)))
            {
                transaction->packet_len = coap_serialize_message(request, transaction->packet);
                coap_send_transaction(transaction);
            }

            etimer_reset(&et);
        }
    } /* while (1) */
#endif
    PROCESS_END();
}
示例#6
0
/*----------------------------------------------------------------------------*/
PROCESS_THREAD(tres_process, ev, data)
{
  PROCESS_BEGIN();

  srand(node_id);
  rest_init_engine();
  tres_init();
  SENSORS_ACTIVATE(light_sensor);
  rest_activate_periodic_resource(&periodic_resource_light);  
  rplinfo_activate_resources();
  static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */
  SERVER_NODE(&server_ipaddr);

  /* receives all CoAP messages */
  coap_receiver_init();
  
  int wait_time = getRandUint(MAX_WAITING);
  int base_wait = BASE_WAITING;
  
  static int g_time=0;
  static char content[12];
  etimer_set(&et, (wait_time + base_wait) * CLOCK_SECOND);

  while(1) {
    PROCESS_YIELD();
    if (etimer_expired(&et)) break;
    }
  etimer_reset(&et);
  etimer_set(&et, TOGGLE_INTERVAL * CLOCK_SECOND);

  while(1) {
    PROCESS_YIELD();
    if (etimer_expired(&et)) {

      coap_init_message(request, COAP_TYPE_NON, COAP_POST, 0 );
      coap_set_header_uri_path(request, service_urls[1]);


      coap_set_payload(request, content, snprintf(content, sizeof(content), "%d", g_time++));

      coap_transaction_t *transaction;

      request->mid = coap_get_mid();
      if ((transaction = coap_new_transaction(request->mid, &server_ipaddr, REMOTE_PORT)))
      {
        transaction->packet_len = coap_serialize_message(request, transaction->packet);
        coap_send_transaction(transaction);
      }

      etimer_reset(&et);
     }
  } /* while (1) */  
  PROCESS_END();
}
示例#7
0
/*-----------------------------------------------------------------------------------*/
void
coap_notify_observers(resource_t *resource, int32_t obs_counter, void *notification)
{
  coap_packet_t *const coap_res = (coap_packet_t *) notification;
  coap_observer_t* obs = NULL;
  uint8_t preferred_type = coap_res->type;

  PRINTF("Observing: Notification from %s\n", resource->url);

  /* Iterate over observers. */
  for (obs = (coap_observer_t*)list_head(observers_list); obs; obs = obs->next)
  {
    if (obs->url==resource->url) /* using RESOURCE url pointer as handle */
    {
      coap_transaction_t *transaction = NULL;

      /*TODO implement special transaction for CON, sharing the same buffer to allow for more observers. */

      if ( (transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port)) )
      {
        PRINTF("           Observer ");
        PRINT6ADDR(&obs->addr);
        PRINTF(":%u\n", obs->port);

        /* Update last MID for RST matching. */
        obs->last_mid = transaction->mid;

        /* Prepare response */
        coap_res->mid = transaction->mid;
        coap_set_header_observe(coap_res, obs_counter);
        coap_set_header_token(coap_res, obs->token, obs->token_len);

        /* Use CON to check whether client is still there/interested after COAP_OBSERVING_REFRESH_INTERVAL. */
        if (stimer_expired(&obs->refresh_timer))
        {
          PRINTF("           Refreshing with CON\n");
          coap_res->type = COAP_TYPE_CON;
          stimer_restart(&obs->refresh_timer);
        }
        else
        {
          coap_res->type = preferred_type;
        }

        transaction->packet_len = coap_serialize_message(coap_res, transaction->packet);

        coap_send_transaction(transaction);
      }
    }
  }
}
示例#8
0
/*---------------------------------------------------------------------------*/
void
coap_notify_observers(resource_t *resource)
{
  /* build notification */
  coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */
  coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
  coap_observer_t *obs = NULL;

  PRINTF("Observe: Notification from %s\n", resource->url);

  /* iterate over observers */
  for(obs = (coap_observer_t *)list_head(observers_list); obs;
      obs = obs->next) {
    if(obs->url == resource->url) {     /* using RESOURCE url pointer as handle */
      coap_transaction_t *transaction = NULL;

      /*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */

      if((transaction = coap_new_transaction(coap_get_mid(), &obs->addr, obs->port))) {
        if(obs->obs_counter % COAP_OBSERVE_REFRESH_INTERVAL == 0) {
          PRINTF("           Force Confirmable for\n");
          notification->type = COAP_TYPE_CON;
        }

        PRINTF("           Observer ");
        PRINT6ADDR(&obs->addr);
        PRINTF(":%u\n", obs->port);

        /* update last MID for RST matching */
        obs->last_mid = transaction->mid;

        /* prepare response */
        notification->mid = transaction->mid;

        resource->get_handler(NULL, notification,
                              transaction->packet + COAP_MAX_HEADER_SIZE,
                              REST_MAX_CHUNK_SIZE, NULL);

        if(notification->code < BAD_REQUEST_4_00) {
          coap_set_header_observe(notification, (obs->obs_counter)++);
        }
        coap_set_token(notification, obs->token, obs->token_len);

        transaction->packet_len =
          coap_serialize_message(notification, transaction->packet);

        coap_send_transaction(transaction);
      }
    }
  }
}
示例#9
0
/**
 * \brief Initiate a separate response with an empty ACK
 * \param request The request to accept
 * \param separate_store A pointer to the data structure that will store the
 *   relevant information for the response
 *
 * When the server does not have enough resources left to store the information
 * for a separate response or otherwise cannot execute the resource handler,
 * this function will respond with 5.03 Service Unavailable. The client can
 * then retry later.
 */
void
coap_separate_accept(void *request, coap_separate_t *separate_store)
{
    coap_packet_t *const coap_req = (coap_packet_t *)request;
    coap_transaction_t *const t = coap_get_transaction_by_mid(coap_req->mid);

    PRINTF("Separate ACCEPT: /%.*s MID %u\n", coap_req->uri_path_len,
           coap_req->uri_path, coap_req->mid);
    if(t) {
        /* send separate ACK for CON */
        if(coap_req->type == COAP_TYPE_CON) {
            coap_packet_t ack[1];

            /* ACK with empty code (0) */
            coap_init_message(ack, COAP_TYPE_ACK, 0, coap_req->mid);
            /* serializing into IPBUF: Only overwrites header parts that are already parsed into the request struct */
            coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
                              (uip_appdata), coap_serialize_message(ack,
                                      uip_appdata));
        }

        /* store remote address */
        uip_ipaddr_copy(&separate_store->addr, &t->addr);
        separate_store->port = t->port;

        /* store correct response type */
        separate_store->type =
            coap_req->type == COAP_TYPE_CON ? COAP_TYPE_CON : COAP_TYPE_NON;
        separate_store->mid = coap_get_mid(); /* if it was a NON, we burned one MID in the engine... */

        memcpy(separate_store->token, coap_req->token, coap_req->token_len);
        separate_store->token_len = coap_req->token_len;

        separate_store->block1_num = coap_req->block1_num;
        separate_store->block1_size = coap_req->block1_size;

        separate_store->block2_num = coap_req->block2_num;
        separate_store->block2_size = coap_req->block2_size > 0 ? MIN(COAP_MAX_BLOCK_SIZE, coap_req->block2_size) : COAP_MAX_BLOCK_SIZE;

        /* signal the engine to skip automatic response and clear transaction by engine */
        erbium_status_code = MANUAL_RESPONSE;
    } else {
        PRINTF("ERROR: Response transaction for separate request not found!\n");
        erbium_status_code = INTERNAL_SERVER_ERROR_5_00;
    }
}
void
oc_send_separate_response(oc_separate_response_t *handle,
                          oc_status_t response_code)
{
  oc_response_buffer_t response_buffer;
  response_buffer.buffer = handle->buffer;
  response_buffer.response_length = response_length();
  response_buffer.code = oc_status_code(response_code);

  coap_separate_t *cur = oc_list_head(handle->requests), *next = NULL;
  coap_packet_t response[1];

  while (cur != NULL) {
    next = cur->next;
    if (cur->observe > 0) {
      coap_transaction_t *t =
        coap_new_transaction(coap_get_mid(), &cur->endpoint);
      if (t) {
        coap_separate_resume(response, cur, oc_status_code(response_code),
                             t->mid);
        coap_set_header_content_format(response, APPLICATION_CBOR);
        if (cur->observe == 1) {
          coap_set_header_observe(response, 1);
        }
        if (response_buffer.response_length > 0) {
          coap_set_payload(response, handle->buffer,
                           response_buffer.response_length);
        }
        t->message->length = coap_serialize_message(response, t->message->data);
        coap_send_transaction(t);
      }
      coap_separate_clear(handle, cur);
    } else {
      if (coap_notify_observers(NULL, &response_buffer, &cur->endpoint) == 0) {
        coap_separate_clear(handle, cur);
      }
    }
    cur = next;
  }
  if (oc_list_length(handle->requests) == 0) {
    handle->active = 0;
  }
}
示例#11
0
PROCESS_THREAD(poti, ev, data)
{

  static struct etimer loop_timer;
  PROCESS_BEGIN();

  /* Initialize the REST engine. */
  rest_init_engine ();
  SERVER_NODE (&server_ipaddr);
  adc_init ();

  /* Activate the application-specific resources. */
#if PLATFORM_HAS_BATTERY
  SENSORS_ACTIVATE(battery_sensor);
  rest_activate_resource (&res_battery,         "s/battery");
#endif
  rest_activate_resource (&res_server_ip,       "poti/ip");
  rest_activate_resource (&res_server_resource, "poti/resource");
  rest_activate_resource (&res_interval,        "poti/interval");

  etimer_set (&loop_timer, LOOP_INTERVAL);
  /* Define application-specific events here. */
  while(1) {
    static int count = 0;
    static int lastval = -1;
    static coap_packet_t request [1]; /* Array: treat as pointer */
    uint8_t val = 127;

    PROCESS_WAIT_EVENT();
    if (etimer_expired (&loop_timer)) {
        uint16_t sum = 0;
        int i;
        count++;
        adc_setup (ADC_DEFAULT, A5);
        for (i=0; i<5; i++) {
            sum += adc_read ();
            clock_delay_usec (50);
        }
        adc_fin ();
        val = (sum / 5) >> 2;
        if ((interval > 0 && count > interval) || (val != lastval)) {
            char buf [4];
            coap_transaction_t *transaction;

            sprintf (buf, "%d", val);
            lastval = val;
            printf ("Sending Value: %s\n", buf);
            coap_init_message (request, COAP_TYPE_NON, COAP_PUT, 0);
            coap_set_header_uri_path (request, server_resource);
            coap_set_header_content_format (request, REST.type.TEXT_PLAIN);
            coap_set_payload (request, buf, strlen (buf));
            request->mid = coap_get_mid ();
            transaction = coap_new_transaction
                (request->mid, &server_ipaddr, REMOTE_PORT);
            transaction->packet_len = coap_serialize_message
                (request, transaction->packet);
            coap_send_transaction (transaction);
            count = 0;
        }
        etimer_reset (&loop_timer);
    }
  } /* while (1) */
示例#12
0
/*----------------------------------------------------------------------------*/
static
int
coap_receive(void)
{
    coap_error_code = NO_ERROR;

    PRINTF("handle_incoming_data(): received uip_datalen=%u \n",(uint16_t)uip_datalen());

    /* Static declaration reduces stack peaks and program code size. */
    static coap_packet_t message[1]; /* This way the packet can be treated as pointer as usual. */
    static coap_packet_t response[1];
    static coap_transaction_t *transaction = NULL;

    if (uip_newdata()) {

        PRINTF("receiving UDP datagram from: ");
        PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
        PRINTF(":%u\n  Length: %u\n  Data: ", uip_ntohs(UIP_UDP_BUF->srcport), uip_datalen() );
        PRINTBITS(uip_appdata, uip_datalen());
        PRINTF("\n");

        coap_error_code = coap_parse_message(message, uip_appdata, uip_datalen());

        if (coap_error_code==NO_ERROR)
        {

            /*TODO duplicates suppression, if required by application */

            PRINTF("  Parsed: v %u, t %u, oc %u, c %u, mid %u\n", message->version, message->type, message->option_count, message->code, message->mid);
            PRINTF("  URL: %.*s\n", message->uri_path_len, message->uri_path);
            PRINTF("  Payload: %.*s\n", message->payload_len, message->payload);

            /* Handle requests. */
            if (message->code >= COAP_GET && message->code <= COAP_DELETE)
            {
                /* Use transaction buffer for response to confirmable request. */
                if ( (transaction = coap_new_transaction(message->mid, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport)) )
                {
                    uint32_t block_num = 0;
                    uint16_t block_size = REST_MAX_CHUNK_SIZE;
                    uint32_t block_offset = 0;
                    int32_t new_offset = 0;

                    /* prepare response */
                    if (message->type==COAP_TYPE_CON)
                    {
                        /* Reliable CON requests are answered with an ACK. */
                        coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->mid);
                    }
                    else
                    {
                        /* Unreliable NON requests are answered with a NON as well. */
                        coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());
                    }

                    /* resource handlers must take care of different handling (e.g., TOKEN_OPTION_REQUIRED_240) */
                    if (IS_OPTION(message, COAP_OPTION_TOKEN))
                    {
                        coap_set_header_token(response, message->token, message->token_len);
                        SET_OPTION(response, COAP_OPTION_TOKEN);
                    }

                    /* get offset for blockwise transfers */
                    if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
                    {
                        PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
                        block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
                        new_offset = block_offset;
                    }

                    /* Invoke resource handler. */
                    if (service_cbk)
                    {
                        /* Call REST framework and check if found and allowed. */
                        if (service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset))
                        {
                            if (coap_error_code==NO_ERROR)
                            {
                                /* Apply blockwise transfers. */
                                if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<BAD_REQUEST_4_00 && !IS_OPTION(response, COAP_OPTION_BLOCK1) )
                                {
                                    PRINTF("Block1 NOT IMPLEMENTED\n");

                                    coap_error_code = NOT_IMPLEMENTED_5_01;
                                    coap_error_message = "NoBlock1Support";
                                }
                                else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) )
                                {
                                    /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                                    if (new_offset==block_offset)
                                    {
                                        PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size);
                                        if (block_offset >= response->payload_len)
                                        {
                                            PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n");

                                            response->code = BAD_OPTION_4_02;
                                            coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                                        }
                                        else
                                        {
                                            coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size);
                                            coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                                        } /* if (valid offset) */
                                    }
                                    else
                                    {
                                        /* resource provides chunk-wise data */
                                        PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset);
                                        coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                                        if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
                                    } /* if (resource aware of blockwise) */
                                }
                                else if (new_offset!=0)
                                {
                                    PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE);

                                    coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
                                    coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
                                } /* if (blockwise request) */
                            } /* no errors/hooks */
                        } /* successful service callback */

                        /* Serialize response. */
                        if (coap_error_code==NO_ERROR)
                        {
                            if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0)
                            {
                                coap_error_code = PACKET_SERIALIZATION_ERROR;
                            }
                        }

                    }
                    else
                    {
                        coap_error_code = NOT_IMPLEMENTED_5_01;
                        coap_error_message = "NoServiceCallbck"; // no a to fit 16 bytes
                    } /* if (service callback) */

                } else {
                    coap_error_code = SERVICE_UNAVAILABLE_5_03;
                    coap_error_message = "NoFreeTraBuffer";
                } /* if (transaction buffer) */
            }
            else
            {
                /* Responses */

                if (message->type==COAP_TYPE_ACK)
                {
                    PRINTF("Received ACK\n");
                }
                else if (message->type==COAP_TYPE_RST)
                {
                    PRINTF("Received RST\n");
                    /* Cancel possible subscriptions. */
                    coap_remove_observer_by_mid(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->mid);
                }

                transaction = coap_get_transaction_by_mid(message->mid);
                if (message->type != COAP_TYPE_CON && transaction)
                {
                    /* Free transaction memory before callback, as it may create a new transaction. */
                    restful_response_handler callback = transaction->callback;
                    void *callback_data = transaction->callback_data;
                    coap_clear_transaction(transaction);

                    /* Check if someone registered for the response */
                    if (callback) {
                        callback(callback_data, message);
                    }
                } /* if (ACKed transaction) */
                /* Observe notification */
                if ((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) \
                        && IS_OPTION(message, COAP_OPTION_OBSERVE)) {
                    PRINTF("Observe [%u]\n", message->observe);
                    coap_handle_notification(&UIP_IP_BUF->srcipaddr,                     \
                                             UIP_UDP_BUF->srcport, message);
                }
                transaction = NULL;

            } /* Request or Response */

        } /* if (parsed correctly) */

        if (coap_error_code==NO_ERROR)
        {
            if (transaction) coap_send_transaction(transaction);
        }
        else if (coap_error_code==MANUAL_RESPONSE)
        {
            PRINTF("Clearing transaction for manual response");
            coap_clear_transaction(transaction);
        }
        else
        {
            PRINTF("ERROR %u: %s\n", coap_error_code, coap_error_message);
            coap_clear_transaction(transaction);

            /* Set to sendable error code. */
            if (coap_error_code >= 192)
            {
                coap_error_code = INTERNAL_SERVER_ERROR_5_00;
            }
            /* Reuse input buffer for error message. */
            coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->mid);
            coap_set_payload(message, coap_error_message, strlen(coap_error_message));
            coap_send_message(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, uip_appdata, coap_serialize_message(message, uip_appdata));
        }
    } /* if (new data) */

    return coap_error_code;
}
示例#13
0
int main(void)
{
  char alias[] = "temp";
  char cik[] = "a32c85ba9dda45823be416246cf8b433baa068d7";

  char host[] = "coap.exosite.com";
  char port[] = "5683";

  srand(time(NULL));

  // CoAP Message Setup
  #define MSG_BUF_LEN 64
  uint8_t msg_send_buf[MSG_BUF_LEN];
  coap_pdu msg_send = {msg_send_buf, 0, 64};
  uint8_t msg_recv_buf[MSG_BUF_LEN];
  coap_pdu msg_recv = {msg_recv_buf, 0, 64};

  uint16_t message_id_counter = rand();

  // Socket to Exosite
  int remotesock;
  size_t bytes_sent;
  ssize_t bytes_recv;
  int rv;

  struct addrinfo exohints, *servinfo, *q;

  memset(&exohints, 0, sizeof exohints);
  exohints.ai_family = AF_UNSPEC;
  exohints.ai_socktype = SOCK_DGRAM;
  exohints.ai_flags = AI_PASSIVE;

  if ((rv = getaddrinfo(host, port, &exohints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
  }


  // loop through all the results and make a socket
  for(q = servinfo; q != NULL; q = q->ai_next) {
    if ((remotesock = socket(q->ai_family, q->ai_socktype, q->ai_protocol)) == -1) {
      perror("bad socket");
      continue;
    }

    break;
  }

  if (q == NULL) {
      fprintf(stderr, "Failed to Bind Socket\n");
      return 2;
  }
 
  for (;;) 
  {
    printf("--------------------------------------------------------------------------------\n");

    // Build Message
    coap_init_pdu(&msg_send);
    //memset(msg_send, 0, msg_send_len);
    coap_set_version(&msg_send, COAP_V1);
    coap_set_type(&msg_send, CT_CON);
    coap_set_code(&msg_send, CC_GET); // or POST to write
    coap_set_mid(&msg_send, message_id_counter++);
    coap_set_token(&msg_send, rand(), 2);
    coap_add_option(&msg_send, CON_URI_PATH, (uint8_t*)"1a", 2);
    coap_add_option(&msg_send, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
    coap_add_option(&msg_send, CON_URI_QUERY, (uint8_t*)cik, strlen(cik));
    // to write, set payload:
    //coap_set_payload(msg_send, &msg_send_len, MSG_BUF_LEN, (uint8_t*)"99", 2);

    // Send Message
    if ((bytes_sent = sendto(remotesock, msg_send.buf, msg_send.len, 0, q->ai_addr, q->ai_addrlen)) == -1){
      fprintf(stderr, "Failed to Send Message\n");
      return 2;
    }

    printf("Sent.\n");
    coap_pretty_print(&msg_send);

    // Wait for Response
    bytes_recv = recvfrom(remotesock, (void *)msg_recv.buf, msg_recv.max, 0, q->ai_addr, &q->ai_addrlen);
    if (bytes_recv < 0) {
      fprintf(stderr, "%s\n", strerror(errno));
      exit(EXIT_FAILURE);
    }

    msg_recv.len = bytes_recv;

    if(coap_validate_pkt(&msg_recv) == CE_NONE)
    {
      printf("Got Valid CoAP Packet\n");
      if(coap_get_mid(&msg_recv) == coap_get_mid(&msg_send) &&
         coap_get_token(&msg_recv) == coap_get_token(&msg_send))
      {
        printf("Is Response to Last Message\n");
        coap_pretty_print(&msg_recv);
      }
    }else{
      printf("Received %zi Bytes, Not Valid CoAP\n", msg_recv.len);
      hex_dump(msg_recv.buf, msg_recv.len);
    }

    sleep(1); // One Second
  }
}
void coap_createCoapRequest(coap_method_t method, const char * uri, ContentType contentType, ObserveState observeState,
        const char * payload, int payloadLen, TransactionCallback callback, void * context)
{
    coap_packet_t request;
    char path[MAX_COAP_PATH] =
    { 0 };
    char query[128] =
    { 0 };
    coap_transaction_t *transaction;
    NetworkAddress * remoteAddress = NetworkAddress_New(uri, strlen(uri));

    coap_getPathQueryFromURI(uri, path, query);

    Lwm2m_Info("Coap request: %s\n", uri);
    //Lwm2m_Debug("Coap request path: %s\n", path);
    //Lwm2m_Debug("Coap request query: %s\n", query);

    coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid());

    coap_set_header_uri_path(&request, path);
    if (strlen(query) > 0)
        coap_set_header_uri_query(&request, query);
    // TODO - REVIEW: Erbium must copy path/query from request - else mem out of scope

    if (contentType != ContentType_None)
    {
        if ((method == COAP_POST) || (method == COAP_PUT))
        {
            coap_set_header_content_format(&request, contentType);
            coap_set_payload(&request, payload, payloadLen);
        }
        else
        {
            coap_set_header_accept(&request, contentType);
        }
    }


    if (method == COAP_GET)
    {
        if (observeState == ObserveState_Establish)
        {
            coap_set_header_observe(&request, 0);
            int token = addObserve(remoteAddress, path, callback, context);
            if (token != 0)
                coap_set_token(&request, (const uint8_t *) &token, sizeof(token));

        }
        else if (observeState == ObserveState_Cancel)
        {
            coap_set_header_observe(&request, 1);
            int token = removeObserve(remoteAddress, path);
            if (token != 0)
                coap_set_token(&request, (const uint8_t *) &token, sizeof(token));
        }
    }

    if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr)
    {
        Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex,
                CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_clear_transaction(&CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
    }

    //if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port))))
    if ((transaction = coap_new_transaction(networkSocket, request.mid, remoteAddress)))
    {
        transaction->callback = coap_CoapRequestCallback;
        memcpy(CurrentTransaction[CurrentTransactionIndex].Path, path, MAX_COAP_PATH);
        CurrentTransaction[CurrentTransactionIndex].Callback = callback;
        CurrentTransaction[CurrentTransactionIndex].Context = context;
        CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true;
        CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction;
        NetworkAddress_SetAddressType(remoteAddress, &CurrentTransaction[CurrentTransactionIndex].Address);

        transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex];

        transaction->packet_len = coap_serialize_message(&request, transaction->packet);

        Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr);
        coap_send_transaction(transaction);

        CurrentTransactionIndex++;

        if (CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS)
        {
            CurrentTransactionIndex = 0;
        }
    }
}
示例#15
0
/* This function is an adaptation of function coap_receive() from Erbium's er-coap-13-engine.c.
 * Erbium is Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
 * All rights reserved.
 */
void lwm2m_handle_packet(lwm2m_context_t * contextP,
                        uint8_t * buffer,
                        int length,
                        void * fromSessionH)
{
    coap_status_t coap_error_code = NO_ERROR;
    static coap_packet_t message[1];
    static coap_packet_t response[1];

    coap_error_code = coap_parse_message(message, buffer, (uint16_t)length);
    if (coap_error_code==NO_ERROR)
    {
        LOG("  Parsed: ver %u, type %u, tkl %u, code %u, mid %u\r\n", message->version, message->type, message->token_len, message->code, message->mid);
        LOG("  Payload: %.*s\r\n\n", message->payload_len, message->payload);

        if (message->code >= COAP_GET && message->code <= COAP_DELETE)
        {
            uint32_t block_num = 0;
            uint16_t block_size = REST_MAX_CHUNK_SIZE;
            uint32_t block_offset = 0;
            int32_t new_offset = 0;

            /* prepare response */
            if (message->type==COAP_TYPE_CON)
            {
                /* Reliable CON requests are answered with an ACK. */
                coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->mid);
            }
            else
            {
                /* Unreliable NON requests are answered with a NON as well. */
                coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());
            }

            /* mirror token */
            if (message->token_len)
            {
                coap_set_header_token(response, message->token, message->token_len);
            }

            /* get offset for blockwise transfers */
            if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
            {
                LOG("Blockwise: block request %u (%u/%u) @ %u bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
                block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
                new_offset = block_offset;
            }

            coap_error_code = handle_request(contextP, fromSessionH, message, response);
            if (coap_error_code==NO_ERROR)
            {
                /* Apply blockwise transfers. */
                if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<BAD_REQUEST_4_00 && !IS_OPTION(response, COAP_OPTION_BLOCK1) )
                {
                    LOG("Block1 NOT IMPLEMENTED\n");

                    coap_error_code = NOT_IMPLEMENTED_5_01;
                    coap_error_message = "NoBlock1Support";
                }
                else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) )
                {
                    /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                    if (new_offset==block_offset)
                    {
                        LOG("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size);
                        if (block_offset >= response->payload_len)
                        {
                            LOG("handle_incoming_data(): block_offset >= response->payload_len\n");

                            response->code = BAD_OPTION_4_02;
                            coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                        }
                        else
                        {
                            coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size);
                            coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                        } /* if (valid offset) */
                    }
                    else
                    {
                        /* resource provides chunk-wise data */
                        LOG("Blockwise: blockwise resource, new offset %d\n", new_offset);
                        coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                        if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
                    } /* if (resource aware of blockwise) */
                }
                else if (new_offset!=0)
                {
                    LOG("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE);

                    coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
                    coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
                } /* if (blockwise request) */

                coap_error_code = message_send(contextP, response, fromSessionH);

                lwm2m_free(response->payload);
                response->payload = NULL;
                response->payload_len = 0;
            }
            else
            {
            	coap_error_code = message_send(contextP, response, fromSessionH);
            }
        }
        else
        {
            /* Responses */
            lwm2m_transaction_t * transaction;

            if (message->type==COAP_TYPE_ACK)
            {
                LOG("Received ACK\n");
            }
            else if (message->type==COAP_TYPE_RST)
            {
                LOG("Received RST\n");
                /* Cancel possible subscriptions. */
                handle_reset(contextP, fromSessionH, message);
            }

#ifdef LWM2M_SERVER_MODE
            if (message->code == COAP_204_CHANGED
             && IS_OPTION(message, COAP_OPTION_OBSERVE))
            {
                handle_observe_notify(contextP, fromSessionH, message);
            }
            else
#endif
            {
                transaction_handle_response(contextP, fromSessionH, message);
            }
        } /* Request or Response */

        coap_free_header(message);

    } /* if (parsed correctly) */
    else
    {
        LOG("Message parsing failed %d\r\n", coap_error_code);
    }

    if (coap_error_code != NO_ERROR)
    {
        LOG("ERROR %u: %s\n", coap_error_code, coap_error_message);

        /* Set to sendable error code. */
        if (coap_error_code >= 192)
        {
            coap_error_code = INTERNAL_SERVER_ERROR_5_00;
        }
        /* Reuse input buffer for error message. */
        coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->mid);
        coap_set_payload(message, coap_error_message, strlen(coap_error_message));
        message_send(contextP, message, fromSessionH);
    }
}
示例#16
0
/*---------------------------------------------------------------------------*/
int
coap_engine_receive(coap_context_t *coap_ctx)
{
  erbium_status_code = NO_ERROR;
  coap_packet_t message[1]; /* this way the packet can be treated as pointer as usual */
  coap_packet_t response[1];
  coap_transaction_t *transaction = NULL;

  PRINTF("%s(): received data len %u\n", __FUNCTION__,
         (uint16_t)uip_appdatalen(coap_ctx->buf));

  if(uip_newdata(coap_ctx->buf)) {

    PRINTF("receiving UDP datagram from: ");
    PRINT6ADDR(&UIP_IP_BUF(coap_ctx->buf)->srcipaddr);
    PRINTF(":%u\n  Length: %u\n",
	   uip_ntohs(UIP_UDP_BUF(coap_ctx->buf)->srcport),
           uip_appdatalen(coap_ctx->buf));

    erbium_status_code =
    coap_parse_message(message, uip_appdata(coap_ctx->buf), uip_appdatalen(coap_ctx->buf));
    coap_set_context(message, coap_ctx);

    if(erbium_status_code == NO_ERROR) {

      NET_COAP_STAT(recv++);

      /*TODO duplicates suppression, if required by application */

      PRINTF("  Parsed: v %u, t %u, tkl %u, c %u, mid %u\n", message->version,
             message->type, message->token_len, message->code, message->mid);
      PRINTF("  URL[%d]: %.*s\n", message->uri_path_len, message->uri_path_len, message->uri_path);
      PRINTF("  Payload[%d]: %.*s\n", message->payload_len, message->payload_len, message->payload);

      /* handle requests */
      if(message->code >= COAP_GET && message->code <= COAP_DELETE) {

        /* use transaction buffer for response to confirmable request */
        if((transaction = coap_new_transaction(message->mid, coap_ctx,
                                               &UIP_IP_BUF(coap_ctx->buf)->srcipaddr,
                                               UIP_UDP_BUF(coap_ctx->buf)->srcport))) {
          uint32_t block_num = 0;
          uint16_t block_size = REST_MAX_CHUNK_SIZE;
          uint32_t block_offset = 0;
          int32_t new_offset = 0;

          /* prepare response */
          if(message->type == COAP_TYPE_CON) {
            /* reliable CON requests are answered with an ACK */
            coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05,
                              message->mid);
          } else {
            /* unreliable NON requests are answered with a NON as well */
            coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05,
                              coap_get_mid());
            /* mirror token */
          } if(message->token_len) {
            coap_set_token(response, message->token, message->token_len);
            /* get offset for blockwise transfers */
          }
          if(coap_get_header_block2
               (message, &block_num, NULL, &block_size, &block_offset)) {
            PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n",
                   (unsigned long)block_num, block_size, REST_MAX_CHUNK_SIZE, (unsigned long)block_offset);
            block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
            new_offset = block_offset;
          }

          /* invoke resource handler */
          if(service_cbk) {

            /* call REST framework and check if found and allowed */
            if(service_cbk
                 (message, response, transaction->packet + COAP_MAX_HEADER_SIZE,
                 block_size, &new_offset)) {

              if(erbium_status_code == NO_ERROR) {

                /* TODO coap_handle_blockwise(request, response, start_offset, end_offset); */

                /* resource is unaware of Block1 */
                if(IS_OPTION(message, COAP_OPTION_BLOCK1)
                   && response->code < BAD_REQUEST_4_00
                   && !IS_OPTION(response, COAP_OPTION_BLOCK1)) {
                  PRINTF("Block1 NOT IMPLEMENTED\n");

                  erbium_status_code = NOT_IMPLEMENTED_5_01;
                  coap_error_message = "NoBlock1Support";

                  /* client requested Block2 transfer */
                } else if(IS_OPTION(message, COAP_OPTION_BLOCK2)) {

                  /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                  if(new_offset == block_offset) {
                    PRINTF
                      ("Blockwise: unaware resource with payload length %u/%u\n",
                      response->payload_len, block_size);
                    if(block_offset >= response->payload_len) {
                      PRINTF
                        ("handle_incoming_data(): block_offset >= response->payload_len\n");

                      response->code = BAD_OPTION_4_02;
                      coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                    } else {
                      coap_set_header_block2(response, block_num,
                                             response->payload_len -
                                             block_offset > block_size,
                                             block_size);
                      coap_set_payload(response,
                                       response->payload + block_offset,
                                       MIN(response->payload_len -
                                           block_offset, block_size));
                    } /* if(valid offset) */

                    /* resource provides chunk-wise data */
                  } else {
                    PRINTF("Blockwise: blockwise resource, new offset %ld\n",
                           (long)new_offset);
                    coap_set_header_block2(response, block_num,
                                           new_offset != -1
                                           || response->payload_len >
                                           block_size, block_size);

                    if(response->payload_len > block_size) {
                      coap_set_payload(response, response->payload,
                                       block_size);
                    }
                  } /* if(resource aware of blockwise) */

                  /* Resource requested Block2 transfer */
                } else if(new_offset != 0) {
                  PRINTF
                    ("Blockwise: no block option for blockwise resource, using block size %u\n",
                    COAP_MAX_BLOCK_SIZE);

                  coap_set_header_block2(response, 0, new_offset != -1,
                                         COAP_MAX_BLOCK_SIZE);
                  coap_set_payload(response, response->payload,
                                   MIN(response->payload_len,
                                       COAP_MAX_BLOCK_SIZE));
                } /* blockwise transfer handling */
              } /* no errors/hooks */
                /* successful service callback */
                /* serialize response */
            }
            if(erbium_status_code == NO_ERROR) {
              if((transaction->packet_len = coap_serialize_message(response,
                                                                   transaction->
                                                                   packet)) ==
                 0) {
                erbium_status_code = PACKET_SERIALIZATION_ERROR;
              }
            }
          } else {
            erbium_status_code = NOT_IMPLEMENTED_5_01;
            coap_error_message = "NoServiceCallbck"; /* no 'a' to fit into 16 bytes */
          } /* if(service callback) */
        } else {
          erbium_status_code = SERVICE_UNAVAILABLE_5_03;
          coap_error_message = "NoFreeTraBuffer";
        } /* if(transaction buffer) */

        /* handle responses */
      } else {

        if(message->type == COAP_TYPE_CON && message->code == 0) {
          PRINTF("Received Ping\n");
          erbium_status_code = PING_RESPONSE;
        } else if(message->type == COAP_TYPE_ACK) {
          /* transactions are closed through lookup below */
          PRINTF("Received ACK\n");
        } else if(message->type == COAP_TYPE_RST) {
          PRINTF("Received RST\n");
          /* cancel possible subscriptions */
          coap_remove_observer_by_mid(coap_ctx, &UIP_IP_BUF(coap_ctx->buf)->srcipaddr,
                                      UIP_UDP_BUF(coap_ctx->buf)->srcport, message->mid);
        }

        if((transaction = coap_get_transaction_by_mid(message->mid))) {
          /* free transaction memory before callback, as it may create a new transaction */
          restful_response_handler callback = transaction->callback;
          void *callback_data = transaction->callback_data;

          coap_clear_transaction(transaction);

          /* check if someone registered for the response */
          if(callback) {
            callback(callback_data, message);
          }
        }
        /* if(ACKed transaction) */
        transaction = NULL;

#if COAP_OBSERVE_CLIENT
	/* if observe notification */
        if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON)
              && IS_OPTION(message, COAP_OPTION_OBSERVE)) {
          PRINTF("Observe [%u]\n", message->observe);
          coap_handle_notification(coap_ctx, &UIP_IP_BUF(coap_ctx->buf)->srcipaddr,
                                   UIP_UDP_BUF(coap_ctx->buf)->srcport, message);
        }
#endif /* COAP_OBSERVE_CLIENT */
      } /* request or response */
    } else { /* parsed correctly */
      NET_COAP_STAT(recv_err++);
    }

    /* if(parsed correctly) */
    if(erbium_status_code == NO_ERROR) {
      if(transaction) {
        coap_send_transaction(transaction);
      }
    } else if(erbium_status_code == MANUAL_RESPONSE) {
      PRINTF("Clearing transaction for manual response");
      coap_clear_transaction(transaction);
    } else {
      coap_message_type_t reply_type = COAP_TYPE_ACK;

      PRINTF("ERROR %u: %s\n", erbium_status_code, coap_error_message);
      coap_clear_transaction(transaction);

      if(erbium_status_code == PING_RESPONSE) {
        erbium_status_code = 0;
        reply_type = COAP_TYPE_RST;
      } else if(erbium_status_code >= 192) {
        /* set to sendable error code */
        erbium_status_code = INTERNAL_SERVER_ERROR_5_00;
        /* reuse input buffer for error message */
      }
      coap_init_message(message, reply_type, erbium_status_code,
                        message->mid);
      coap_set_payload(message, coap_error_message,
                       strlen(coap_error_message));
      coap_send_message(coap_ctx, &UIP_IP_BUF(coap_ctx->buf)->srcipaddr,
			UIP_UDP_BUF(coap_ctx->buf)->srcport,
                        uip_appdata(coap_ctx->buf),
			coap_serialize_message(message,
					       uip_appdata(coap_ctx->buf)));
    }
  }

  /* if(new data) */
  return erbium_status_code;
}
示例#17
0
void ICACHE_FLASH_ATTR coap_send(void *pvParameters)
//int coap_send(void)
{
    char *url = "coap.me";
    int port = 5683;
    
    uint16_t message_id_counter = rand();

    printf("%d,%d",message_id_counter, port);
    
    int sock;
    int bytes_sent;
    int bytes_recv;
    
    struct hostent *host;
    struct sockaddr_in server_addr;
    
    /* 通过函数入口参数url获得host地址*/
    host= (struct hostent *) gethostbyname(url);
    printf("here");
    /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        printf("Socket Error\n");
    }
    printf("here2");
    /* 初始化预连接的服务端地址 */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    
    printf("--------------------\r\n");
    
    // Build Message
    coap_init_pdu(&msg_send);
    //memset(msg_send, 0, msg_send_len);
    coap_set_version(&msg_send, COAP_V1);
    coap_set_type(&msg_send, CT_CON);
    coap_set_code(&msg_send, CC_GET); // or POST to write
    coap_set_mid(&msg_send, message_id_counter++);
    // coap_set_token(&msg_send, rand(), 2);
    coap_add_option(&msg_send, CON_URI_PATH, (uint8_t*)"hello", strlen("hello"));
    // coap_add_option(&msg_send, CON_URI_PATH, (uint8_t*)alias, strlen(alias));
    // coap_add_option(&msg_send, CON_URI_QUERY, (uint8_t*)cik, strlen(cik));
    // to write, set payload:
    //coap_set_payload(msg_send, &msg_send_len, MSG_BUF_LEN, (uint8_t*)"99", 2);
    
    // Send Message
    if ((bytes_sent = sendto(sock, msg_send.buf, msg_send.len, 0, 
                             (struct sockaddr *)&server_addr, sizeof(struct sockaddr))) == -1)
    {
        printf("Failed to Send Message\r\n");
    }
    else{
	printf("bytes %d\n",bytes_sent);	
    }

     socklen_t len = sizeof(server_addr);
    
     bytes_recv = recvfrom(sock, (void *)msg_recv.buf, msg_recv.max, 0, (struct sockaddr *)&server_addr,&len);
   
    if (bytes_recv < 0) {
      printf("game over baby\n");
    }
    else{
	printf("yuhu\n");
    }

    msg_recv.len = bytes_recv;

    if(coap_validate_pkt(&msg_recv) == CE_NONE)
    {
      printf("Got Valid CoAP Packet\n");
      if(coap_get_mid(&msg_recv) == coap_get_mid(&msg_send) &&
         coap_get_token(&msg_recv) == coap_get_token(&msg_send))
      {
        printf("Is Response to Last Message\n");
        coap_pretty_print(&msg_recv);
      }
    }else{
      printf("Received %zi Bytes, Not Valid CoAP\n", msg_recv.len);
    }    
  vTaskDelete(NULL);	
}
示例#18
0
void
http_get_task(void *pvParameters)
{
    coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */
    int failures = 0;

    // create network socket
    struct addrinfo hints;
    struct addrinfo *res;

    // Use an UDP socket
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    // Get host/port from request URL
    // should call free(uri) somewhere
    coap_uri_t *uri = coap_new_uri((unsigned char*)URI, strlen(URI));   
    if (uri == NULL) {
        COAP_PRINTF("coap_new_uri(): URI failed\n");
        vTaskDelete(NULL);
    }

    // DNS lookup
    int err;
    char port[6];
    char host[32];
    char path[64];

    sprintf(port, "%d", uri->port);
    sprintf(path, "%s", uri->path.s);
    memcpy(host, uri->host.s, uri->host.length);
    host[uri->host.length] = '\0';

    COAP_PRINTF("URI Path: %s\n", path);
    COAP_PRINTF("URI Host: %s\n", host);
    COAP_PRINTF("URI Port: %s\n", port);

    printf("Running DNS lookup for %s...\r\n", host);

    while (1) {
        err = getaddrinfo(host, port, &hints, &res);
        if (err == 0)
            break;
        freeaddrinfo(res);
        printf("DNS lookup failed err=%d res=%p\r\n", err, res);
        vTaskDelay(3000 / portTICK_RATE_MS);
    }

    /* Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
    struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
    char *ip = inet_ntoa(*addr);
    printf("DNS lookup succeeded. HOST=%s, IP=%s\r\n", host, ip);

    // init a HTTP POST message and set message header
    coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
    coap_set_header_uri_path(request, path);
    coap_set_header_uri_host(request, host);

    // Create a local socket
    int s = socket(res->ai_family, res->ai_socktype, 0);
    if(s < 0) {
        printf("... Failed to allocate socket.\r\n");
        freeaddrinfo(res);
        vTaskDelete(NULL);
    }

    printf("... allocated socket\r\n");

    int a;
    int ret;
    char payload[128];
    struct request_state_t state[1];
    ip_addr_t ipaddr;

    ipaddr.addr = ipaddr_addr(ip);

    while(1) {
        if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
            close(s);
            freeaddrinfo(res);
            printf("... socket connect failed.\r\n");
            vTaskDelay(3000 / portTICK_RATE_MS);
            failures++;
            continue;
        }

        printf("... connected\r\n");
        freeaddrinfo(res);
repeat:
        vTaskDelay(5000 / portTICK_RATE_MS);

        // read sensor data from ESP8266 A0
        a = sdk_system_adc_read();

        sprintf(payload, "{ \"quality\": %d }\n", a);
        COAP_PRINTF("Payload: %s\n", payload);

        // CoAP payload
        coap_set_payload(request, payload, strlen(payload));

        // Make CoAP transaction
        request->mid = coap_get_mid();

        if ((state->transaction = coap_new_transaction(request->mid, &ipaddr, uri->port)))
        {
            state->transaction->callback = coap_blocking_request_callback;
            state->transaction->callback_data = state;

            if (state->block_num > 0)
            {
                coap_set_header_block2(request, state->block_num, 0, REST_MAX_CHUNK_SIZE);
            }

            // Build CoAP header and Options
            state->transaction->packet_len = coap_serialize_message(request, state->transaction->packet);

            COAP_PRINTF("Header dump: [0x%02X %02X %02X %02X]. Size: %d\n",
                request->buffer[0],
                request->buffer[1],
                request->buffer[2],
                request->buffer[3],
                state->transaction->packet_len
            );

            COAP_PRINTF("Requested #%u (MID %u)\n", state->block_num, request->mid);

            // Transmit
            ret = write(s, state->transaction->packet, state->transaction->packet_len);
            //ret = sendto(s, state->transaction->packet, state->transaction->packet_len);
            if (ret < 0) {
                printf("[RET: %d] CoAP packet send failed.\n", ret);
                continue;
            }
        }
        else
        {
          COAP_PRINTF("Could not allocate transaction buffer");
        }

        goto repeat;
    }
}
示例#19
0
    // server CB
    int request1 (void* transaction_, void* data) {
#if COAP_CEU
        CEU_Transaction* transaction = (CEU_Transaction*) transaction_;
#else
        coap_transaction_t* transaction = (coap_transaction_t*) transaction_;
#endif
        /* Use transaction buffer for response to confirmable request. */
          uint32_t block_num = 0;
          uint16_t block_size = REST_MAX_CHUNK_SIZE;
          uint32_t block_offset = 0;
          int32_t new_offset = 0;

          /* prepare response */
          if (message->type==COAP_TYPE_CON)
          {
            /* Reliable CON requests are answered with an ACK. */
            coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->mid);
          }
          else
          {
            /* Unreliable NON requests are answered with a NON as well. */
            coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid());
          }

          /* mirror token */
          if (message->token_len)
          {
              coap_set_header_token(response, message->token, message->token_len);
          }

          /* get offset for blockwise transfers */
          if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
          {
              PRINTF("Blockwise: block request %lu (%u/%u) @ %lu bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
              block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
              new_offset = block_offset;
          }

          /* Invoke resource handler. */
          if (service_cbk)
          {
            /* Call REST framework and check if found and allowed. */
            if (service_cbk(message, response, transaction->packet+COAP_MAX_HEADER_SIZE, block_size, &new_offset))
            {
              if (coap_error_code==NO_ERROR)
              {
                /* Apply blockwise transfers. */
                if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<BAD_REQUEST_4_00 && !IS_OPTION(response, COAP_OPTION_BLOCK1) )
                {
                  PRINTF("Block1 NOT IMPLEMENTED\n");

                  coap_error_code = NOT_IMPLEMENTED_5_01;
                  coap_error_message = "NoBlock1Support";
                }
                else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) )
                {
                  /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                  if (new_offset==block_offset)
                  {
                    PRINTF("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size);
                    if (block_offset >= response->payload_len)
                    {
                      PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n");

                      response->code = BAD_OPTION_4_02;
                      coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                    }
                    else
                    {
                      coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size);
                      coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                    } /* if (valid offset) */
                  }
                  else
                  {
                    /* resource provides chunk-wise data */
                    PRINTF("Blockwise: blockwise resource, new offset %ld\n", new_offset);
                    coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                    if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
                  } /* if (resource aware of blockwise) */
                }
                else if (new_offset!=0)
                {
                  PRINTF("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE);

                  coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
                  coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
                } /* if (blockwise request) */
              } /* no errors/hooks */
            } /* successful service callback */

            /* Serialize response. */
            if (coap_error_code==NO_ERROR)
            {
              if ((transaction->packet_len = coap_serialize_message(response, transaction->packet))==0)
              {
                coap_error_code = PACKET_SERIALIZATION_ERROR;
              }
            }

          }
          else
          {
            coap_error_code = NOT_IMPLEMENTED_5_01;
            coap_error_message = "NoServiceCallbck"; // no a to fit 16 bytes
          } /* if (service callback) */

          return coap_error_code;
    }
示例#20
0
/*---------------------------------------------------------------------------*/
int
coap_receive(oc_message_t *msg)
{
  erbium_status_code = NO_ERROR;

  LOG("\n\nCoAP Engine: received datalen=%u \n", (unsigned int) msg->length);

  /* static declaration reduces stack peaks and program code size */
  static coap_packet_t
    message[1]; /* this way the packet can be treated as pointer as usual */
  static coap_packet_t response[1];
  static coap_transaction_t *transaction = NULL;

  erbium_status_code = coap_parse_message(message, msg->data, msg->length);

  if (erbium_status_code == NO_ERROR) {

/*TODO duplicates suppression, if required by application */

#if DEBUG
    LOG("  Parsed: CoAP version: %u, token: 0x%02X%02X, mid: %u\n",
        message->version, message->token[0], message->token[1], message->mid);
    switch (message->type) {
    case COAP_TYPE_CON:
      LOG("  type: CON\n");
      break;
    case COAP_TYPE_NON:
      LOG("  type: NON\n");
      break;
    case COAP_TYPE_ACK:
      LOG("  type: ACK\n");
      break;
    case COAP_TYPE_RST:
      LOG("  type: RST\n");
      break;
    default:
      break;
    }
#endif

    /* handle requests */
    if (message->code >= COAP_GET && message->code <= COAP_DELETE) {

#if DEBUG
      switch (message->code) {
      case COAP_GET:
        LOG("  method: GET\n");
        break;
      case COAP_PUT:
        LOG("  method: PUT\n");
        break;
      case COAP_POST:
        LOG("  method: POST\n");
        break;
      case COAP_DELETE:
        LOG("  method: DELETE\n");
        break;
      }
      LOG("  URL: %.*s\n", (int) message->uri_path_len, message->uri_path);
      LOG("  Payload: %.*s\n", (int) message->payload_len, message->payload);
#endif
      /* use transaction buffer for response to confirmable request */
      if ((transaction = coap_new_transaction(message->mid, &msg->endpoint))) {
        uint32_t block_num = 0;
        uint16_t block_size = COAP_MAX_BLOCK_SIZE;
        uint32_t block_offset = 0;
        int32_t new_offset = 0;

        /* prepare response */
        if (message->type == COAP_TYPE_CON) {
          /* reliable CON requests are answered with an ACK */
          coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05,
                            message->mid);
        } else {
          /* unreliable NON requests are answered with a NON as well */
          coap_init_message(response, COAP_TYPE_NON, CONTENT_2_05,
                            coap_get_mid());
          /* mirror token */
        }
        if (message->token_len) {
          coap_set_token(response, message->token, message->token_len);
          /* get offset for blockwise transfers */
        }
        if (coap_get_header_block2(message, &block_num, NULL, &block_size,
                                   &block_offset)) {
          LOG("\tBlockwise: block request %u (%u/%u) @ %u bytes\n", (unsigned int) block_num,
              block_size, COAP_MAX_BLOCK_SIZE, (unsigned int) block_offset);
          block_size = MIN(block_size, COAP_MAX_BLOCK_SIZE);
          new_offset = block_offset;
        }

        /* invoke resource handler in RI layer */
        if (oc_ri_invoke_coap_entity_handler(
              message, response,
              transaction->message->data + COAP_MAX_HEADER_SIZE, block_size,
              &new_offset, &msg->endpoint)) {

          if (erbium_status_code == NO_ERROR) {

            /* TODO coap_handle_blockwise(request, response, start_offset,
             * end_offset); */

            /* resource is unaware of Block1 */
            if (IS_OPTION(message, COAP_OPTION_BLOCK1) &&
                response->code < BAD_REQUEST_4_00 &&
                !IS_OPTION(response, COAP_OPTION_BLOCK1)) {
              LOG("\tBlock1 option NOT IMPLEMENTED\n");

              erbium_status_code = NOT_IMPLEMENTED_5_01;
              coap_error_message = "NoBlock1Support";

              /* client requested Block2 transfer */
            } else if (IS_OPTION(message, COAP_OPTION_BLOCK2)) {

              /* unchanged new_offset indicates that resource is unaware of
               * blockwise transfer */
              if (new_offset == block_offset) {
                LOG("\tBlockwise: unaware resource with payload length %u/%u\n",
                    response->payload_len, block_size);
                if (block_offset >= response->payload_len) {
                  LOG("\t\t: block_offset >= response->payload_len\n");

                  response->code = BAD_OPTION_4_02;
                  coap_set_payload(response, "BlockOutOfScope",
                                   15); /* a const char str[] and sizeof(str)
                                           produces larger code size */
                } else {
                  coap_set_header_block2(response, block_num,
                                         response->payload_len - block_offset >
                                           block_size,
                                         block_size);
                  coap_set_payload(
                    response, response->payload + block_offset,
                    MIN(response->payload_len - block_offset, block_size));
                } /* if(valid offset) */

                /* resource provides chunk-wise data */
              } else {
                LOG("\tBlockwise: blockwise resource, new offset %d\n",
                    (int) new_offset);
                coap_set_header_block2(response, block_num,
                                       new_offset != -1 ||
                                         response->payload_len > block_size,
                                       block_size);

                if (response->payload_len > block_size) {
                  coap_set_payload(response, response->payload, block_size);
                }
              } /* if(resource aware of blockwise) */

              /* Resource requested Block2 transfer */
            } else if (new_offset != 0) {
              LOG("\tBlockwise: no block option for blockwise resource, using "
                  "block size %u\n",
                  COAP_MAX_BLOCK_SIZE);

              coap_set_header_block2(response, 0, new_offset != -1,
                                     COAP_MAX_BLOCK_SIZE);
              coap_set_payload(response, response->payload,
                               MIN(response->payload_len, COAP_MAX_BLOCK_SIZE));
            } /* blockwise transfer handling */
          }   /* no errors/hooks */
          /* successful service callback */
          /* serialize response */
        }
        if (erbium_status_code == NO_ERROR) {
          if ((transaction->message->length = coap_serialize_message(
                 response, transaction->message->data)) == 0) {
            erbium_status_code = PACKET_SERIALIZATION_ERROR;
          }
        }
      } else {
        erbium_status_code = SERVICE_UNAVAILABLE_5_03;
        coap_error_message = "NoFreeTraBuffer";
      } /* if(transaction buffer) */

      /* handle responses */
    } else { // Fix this
      if (message->type == COAP_TYPE_CON) {
        erbium_status_code = EMPTY_ACK_RESPONSE;
      } else if (message->type == COAP_TYPE_ACK) {
        /* transactions are closed through lookup below */
      } else if (message->type == COAP_TYPE_RST) {
#ifdef OC_SERVER
        /* cancel possible subscriptions */
        coap_remove_observer_by_mid(&msg->endpoint, message->mid);
#endif
      }

      /* Open transaction now cleared for ACK since mid matches */
      if ((transaction = coap_get_transaction_by_mid(message->mid))) {
        coap_clear_transaction(transaction);
      }
      /* if(ACKed transaction) */
      transaction = NULL;

#ifdef OC_CLIENT // ACKs and RSTs sent to oc_ri.. RSTs cleared, ACKs sent to
                 // client
      oc_ri_invoke_client_cb(message, &msg->endpoint);
#endif

    } /* request or response */
  }   /* parsed correctly */

  /* if(parsed correctly) */
  if (erbium_status_code == NO_ERROR) {
    if (transaction) { // Server transactions sent from here
      coap_send_transaction(transaction);
    }
  } else if (erbium_status_code == CLEAR_TRANSACTION) {
    LOG("Clearing transaction for manual response");
    coap_clear_transaction(transaction); // used in server for separate response
  }
#ifdef OC_CLIENT
  else if (erbium_status_code == EMPTY_ACK_RESPONSE) {
    coap_init_message(message, COAP_TYPE_ACK, 0, message->mid);
    oc_message_t *response = oc_allocate_message();
    if (response) {
      memcpy(&response->endpoint, &msg->endpoint, sizeof(msg->endpoint));
      response->length = coap_serialize_message(message, response->data);
      coap_send_message(response);
    }
  }
#endif /* OC_CLIENT */
#ifdef OC_SERVER
  else { // framework errors handled here
    coap_message_type_t reply_type = COAP_TYPE_RST;

    coap_clear_transaction(transaction);

    coap_init_message(message, reply_type, SERVICE_UNAVAILABLE_5_03,
                      message->mid);

    oc_message_t *response = oc_allocate_message();
    if (response) {
      memcpy(&response->endpoint, &msg->endpoint, sizeof(msg->endpoint));
      response->length = coap_serialize_message(message, response->data);
      coap_send_message(response);
    }
  }
#endif /* OC_SERVER */

  /* if(new data) */
  return erbium_status_code;
}