14 #include <sys/select.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
29 #define COAP_RESOURCE_CHECK_TIME_SEC 1
32 #define min(a,b) ((a) < (b) ? (a) : (b))
38 #define COAP_OPT_BLOCK_SZX_MAX 6
40 #define REQUIRE_ETAG 0x01
76 #define INDEX "libcoap server for ETSI CoAP Plugtest, March 2012, Paris\n" \
77 "Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
132 unsigned char buf[3];
151 unsigned char buf[2];
169 memset(etag, 0,
sizeof(etag));
246 size_t l = 6 +
sizeof(
void *);
253 unsigned char *buf = _buf;
261 if (!(test_payload && uri)) {
262 coap_log(LOG_CRIT,
"cannot allocate new resource under /test");
270 uri->
length =
min(l, snprintf((
char *)uri->
data, l,
"test/%p", test_payload));
271 test_payload->
length = len;
273 memcpy(test_payload->
data, data, len);
319 if (payload && payload->
max_data < len) {
334 memcpy(payload->
data, data, len);
351 warn(
"cannot modify resource\n");
379 unsigned char buf[70];
393 L =
min(
sizeof(buf) - len, 11);
394 memcpy(buf + len,
"Uri-Query: ", L);
401 if (len <
sizeof(buf))
416 unsigned long delay = 5;
419 if (async->
id != request->
hdr->
id) {
445 debug(
"set delay to %lu\n", delay);
451 (
void *)(COAP_TICKS_PER_SECOND * delay));
458 unsigned char buf[2];
461 if (!async || now < async->created + (
unsigned long)async->
appdata)
471 debug(
"check_async: insufficient memory, we'll try later\n");
473 (
void *)((
unsigned long)async->
appdata + 15 * COAP_TICKS_PER_SECOND);
488 debug(
"check_async: cannot send response for message %d\n",
501 FILE *inputfile = NULL;
508 if (stat(filename, &statbuf) < 0) {
509 warn(
"cannot stat file %s\n", filename);
517 inputfile = fopen(filename,
"r");
519 warn(
"cannot read file %s\n", filename);
524 payload->
length = fread(payload->
data, 1, statbuf.st_size, inputfile);
539 coap_log(LOG_CRIT,
"cannot allocate resource /test");
541 test_payload->
length = 13;
542 memcpy(test_payload->
data,
"put data here", test_payload->
length);
551 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
552 coap_add_attr(r, (
unsigned char *)
"rt", 2, (
unsigned char *)
"test", 4, 0);
553 coap_add_attr(r, (
unsigned char *)
"if", 2, (
unsigned char *)
"core#b", 6, 0);
563 test_payload =
make_large(
"etsi_iot_01_largedata.txt");
565 coap_log(LOG_CRIT,
"cannot allocate resource /large\n");
570 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"41", 2, 0);
571 coap_add_attr(r, (
unsigned char *)
"rt", 2, (
unsigned char *)
"large", 5, 0);
582 coap_log(LOG_CRIT,
"cannot allocate resource /seg1/seg2/seg3\n");
584 test_payload->
length = 10;
585 memcpy(test_payload->
data,
"segsegseg!", test_payload->
length);
591 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
601 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
608 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
609 coap_add_attr(r, (
unsigned char *)
"rt", 2, (
unsigned char *)
"separate", 8, 0);
614 usage(
const char *program,
const char *version) {
617 p = strrchr( program,
'/' );
621 fprintf( stderr,
"%s v%s -- ETSI CoAP plugtest server\n"
622 "(c) 2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
623 "usage: %s [-A address] [-p port]\n\n"
624 "\t-A address\tinterface address to bind to\n"
625 "\t-p port\t\tlisten on specified port\n"
626 "\t-v num\t\tverbosity level (default: 3)\n",
627 program, version, program );
634 struct addrinfo hints;
635 struct addrinfo *result, *rp;
637 memset(&hints, 0,
sizeof(
struct addrinfo));
638 hints.ai_family = AF_UNSPEC;
639 hints.ai_socktype = SOCK_DGRAM;
640 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
642 s = getaddrinfo(node, port, &hints, &result);
644 fprintf(stderr,
"getaddrinfo: %s\n", gai_strerror(s));
649 for (rp = result; rp != NULL; rp = rp->ai_next) {
652 if (rp->ai_addrlen <=
sizeof(addr.addr)) {
654 addr.size = rp->ai_addrlen;
655 memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen);
665 fprintf(stderr,
"no context available for interface '%s'\n", node);
668 freeaddrinfo(result);
676 struct timeval tv, *timeout;
680 char addr_str[NI_MAXHOST] =
"::";
681 char port_str[NI_MAXSERV] =
"5683";
685 while ((opt = getopt(argc, argv,
"A:p:v:")) != -1) {
688 strncpy(addr_str, optarg, NI_MAXHOST-1);
689 addr_str[NI_MAXHOST - 1] =
'\0';
692 strncpy(port_str, optarg, NI_MAXSERV-1);
693 port_str[NI_MAXSERV - 1] =
'\0';
696 log_level = strtol(optarg, NULL, 10);
718 FD_SET( ctx->sockfd, &readfds );
723 while ( nextpdu && nextpdu->
t <= now ) {
730 tv.tv_usec = ((nextpdu->
t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
731 tv.tv_sec = (nextpdu->
t - now) / COAP_TICKS_PER_SECOND;
738 result = select( FD_SETSIZE, &readfds, 0, 0, timeout );
743 }
else if ( result > 0 ) {
744 if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block)
Initializes block from pdu.
#define COAP_RESOURCE_CHECK_TIME_SEC
#define COAP_REQUEST_POST
void hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
void * appdata
This field can be used to register opaque application data with the asynchronous state object...
int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu, size_t data_length)
Writes a block option of type type to message pdu.
unsigned char coap_key_t[4]
#define COAP_RESPONSE_CODE(N)
void coap_dispatch(coap_context_t *context)
Dispatches the PDUs from the receive queue in given context.
int coap_delete_resource(coap_context_t *context, coap_key_t key)
Deletes a resource identified by key.
coap_payload_t * coap_new_payload(size_t size)
coap_payload_t * test_resources
int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data)
Adds token of length len to pdu.
unsigned char flags
holds the flags to control behaviour
coap_opt_t * coap_check_option(coap_pdu_t *pdu, unsigned char type, coap_opt_iterator_t *oi)
Retrieves the first option of type type from pdu.
static coap_payload_t * coap_find_payload(const coap_key_t key)
coap_context_t * get_context(const char *node, const char *port)
void hnd_delete_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
static void coap_register_option(coap_context_t *ctx, unsigned char type)
Registers the option type type with the given context object ctx.
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_address_t peer
the peer to notify
int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data)
Retrieves the length and data pointer of specified PDU.
#define COAP_OPTION_MAXAGE
#define coap_malloc(size)
void handle_sigint(int signum)
void check_async(coap_context_t *ctx, coap_tick_t now)
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
coap_payload_t * make_large(char *filename)
#define COAP_OPTION_CONTENT_TYPE
static int coap_option_setb(coap_opt_filter_t filter, unsigned short type)
Sets the corresponding bit for type in filter.
coap_context_t * coap_new_context(const coap_address_t *listen_addr)
Creates a new coap_context_t object that will hold the CoAP stack status.
static coap_async_state_t * async
coap_queue_t * coap_peek_next(coap_context_t *context)
Returns the next pdu to send without removing from sendqeue.
void hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
static void coap_delete_payload(coap_payload_t *payload)
coap_tick_t t
when to send PDU for the next time
coap_tid_t id
transaction id
#define HASH_DELETE(hh, head, delptr)
coap_attr_t * coap_add_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen, const unsigned char *val, size_t vlen, int flags)
Registers a new attribute with the given resource.
void hnd_put_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
Header structure for CoAP PDUs.
coap_opt_iterator_t * coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t filter)
Initializes the given option iterator oi to point to the beginning of the pdu's option list...
coap_key_t key
the actual key bytes for this resource
static void coap_add_payload(const coap_key_t key, coap_payload_t *payload, coap_dynamic_uri_t *uri)
coap_async_state_t * coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request, unsigned char flags, void *data)
Allocates a new coap_async_state_t object and fills its fields according to the given request...
unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val)
Encodes multiple-length byte sequences.
static void coap_register_handler(coap_resource_t *resource, unsigned char method, coap_method_handler_t handler)
Registers the specified handler as message handler for the request type method.
#define COAP_ASYNC_CONFIRM
send confirmable response
void hnd_post_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, unsigned int block_num, unsigned char block_szx)
Adds the block_num block of size 1 << (block_szx + 4) from source data to pdu.
void coap_add_resource(coap_context_t *context, coap_resource_t *resource)
Registers the given resource for context.
int coap_split_path(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen)
Splits the given URI path into segments.
Iterator to run through PDU options.
size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data)
de-duplicate code with coap_add_option_later
#define COAP_OPT_SIZE(opt)
unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3)+1]
Fixed-size bit-vector we use for option filtering.
int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data)
Adds given data to the pdu that is passed as first parameter.
#define coap_hash(String, Length, Result)
#define COAP_ASYNC_SEPARATE
send separate response
#define COAP_REQUEST_DELETE
coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu)
Sends a non-confirmed CoAP message to given destination.
#define COAP_OPTION_BLOCK2
#define COAP_OPTION_LOCATION_PATH
void coap_delete_pdu(coap_pdu_t *pdu)
static void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
coap_pdu_t * coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size)
Creates a new CoAP PDU of given size (must be large enough to hold the basic CoAP message header (coa...
Structure of Block options.
static void coap_option_filter_clear(coap_opt_filter_t f)
Clears filter f.
int coap_remove_async(coap_context_t *context, coap_tid_t id, coap_async_state_t **s)
Removes the state object identified by id from context.
void coap_free_async(coap_async_state_t *s)
Releases the memory that was allocated by coap_async_state_init() for the object s.
void coap_free_context(coap_context_t *context)
#define COAP_OPT_LENGTH(opt)
size_t tokenlen
length of the token
static unsigned short coap_new_message_id(coap_context_t *context)
Returns a new message id and updates context->message_id accordingly.
This structure is used to store URIs for dynamically allocated resources, usually by POST or PUT...
coap_resource_t * coap_resource_init(const unsigned char *uri, size_t len, int flags)
Creates a new resource object and initializes the link field to the string of length len...
void init_resources(coap_context_t *ctx)
#define COAP_MEDIATYPE_TEXT_PLAIN
#define HASH_ADD(hh, head, fieldname, keylen_in, add)
int main(int argc, char **argv)
void coap_set_log_level(coap_log_t level)
Sets the log level to the specified value.
unsigned char token[]
the token to use in a response
#define COAP_OPTION_URI_QUERY
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)
unsigned char coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
char * coap_response_phrase(unsigned char code)
Returns a human-readable response phrase for the specified CoAP response code.
int coap_read(coap_context_t *ctx)
Reads data from the network and tries to parse as CoAP PDU.
#define HASH_FIND(hh, head, keyptr, keylen, out)
void usage(const char *program, const char *version)
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node)
Handles retransmissions of confirmable messages.
void hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
unsigned int coap_decode_var_bytes(unsigned char *buf, unsigned int len)
Decodes multiple-length byte sequences.
coap_queue_t * coap_pop_next(coap_context_t *context)
Returns the next pdu to send and removes it from the sendqeue.
coap_dynamic_uri_t * test_dynamic_uris
#define COAP_OPT_VALUE(opt)
The CoAP stack's global state is stored in a coap_context_t object.
unsigned int szx
block size
unsigned int num
block number