/* * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file is part of the Contiki operating system. */ /** * \file * Example resource * \author * Matthias Kovatsch */ #include #include "rest-engine.h" #include "er-coap-separate.h" #include "er-coap-transactions.h" static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); static void res_resume_handler(void); SEPARATE_RESOURCE(res_separate1, "title=\"Separate demo\"", res_get_handler, NULL, NULL, NULL, res_resume_handler); /* A structure to store the information required for the separate handler */ typedef struct application_separate_store { /* Provided by Erbium to store generic request information such as remote address and token. */ coap_separate_t request_metadata; /* Add fields for addition information to be stored for finalizing, e.g.: */ char buffer[16]; } application_separate_store_t; #define COAP_MAX_OPEN_SEPARATE 2 static uint8_t separate_active = 0; static application_separate_store_t separate_store[COAP_MAX_OPEN_SEPARATE]; static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { /* * Example allows only one open separate response. * For multiple, the application must manage the list of stores. */ if(separate_active >= COAP_MAX_OPEN_SEPARATE) { coap_separate_reject(); } else { ++separate_active; /* Take over and skip response by engine. */ coap_separate_accept(request, &separate_store->request_metadata); /* Be aware to respect the Block2 option, which is also stored in the coap_separate_t. */ /* * At the moment, only the minimal information is stored in the store (client address, port, token, MID, type, and Block2). * Extend the store, if the application requires additional information from this handler. * buffer is an example field for custom information. */ snprintf(separate_store->buffer, sizeof(separate_store->buffer), "StoredInfo"); } } static void res_resume_handler() { if(separate_active) { coap_transaction_t *transaction = NULL; if((transaction = coap_new_transaction(separate_store->request_metadata.mid, &separate_store->request_metadata.addr, separate_store->request_metadata.port))) { coap_packet_t response[1]; /* This way the packet can be treated as pointer as usual. */ /* Restore the request information for the response. */ coap_separate_resume(response, &separate_store->request_metadata, REST.status.OK); coap_set_payload(response, separate_store->buffer, strlen(separate_store->buffer)); /* * Be aware to respect the Block2 option, which is also stored in the coap_separate_t. * As it is a critical option, this example resource pretends to handle it for compliance. */ coap_set_header_block2(response, separate_store->request_metadata.block2_num, 0, separate_store->request_metadata.block2_size); /* Warning: No check for serialization error. */ transaction->packet_len = coap_serialize_message(response, transaction->packet); coap_send_transaction(transaction); /* The engine will clear the transaction (right after send for NON, after acked for CON). */ /* FIXME there could me more! */ separate_active = 0; } else { /* * Set timer for retry, send error message, ... * The example simply waits for another button press. */ } } /* if (separate_active) */ }