15 #include <sys/select.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
30 #define COAP_RESOURCE_CHECK_TIME 2
33 #define min(a,b) ((a) < (b) ? (a) : (b))
56 #define INDEX "This is a test server made with libcoap (see http://libcoap.sf.net)\n" \
57 "Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>\n\n"
82 unsigned char buf[40];
95 if (request != NULL &&
103 if (resource->
dirty == 1)
126 len = snprintf((
char *)buf,
128 "%u", (
unsigned int)now);
134 len = strftime((
char *)buf,
136 "%b %d %H:%M:%S", tmp);
184 #ifndef WITHOUT_ASYNC
191 unsigned long delay = 5;
195 if (async->
id != request->
hdr->
id) {
209 delay = delay * 10 + (*p -
'0');
214 (
void *)(COAP_TICKS_PER_SECOND * delay));
224 if (!async || now < async->created + (
unsigned long)async->
appdata)
232 debug(
"check_async: insufficient memory, we'll try later\n");
234 (
void *)((
unsigned long)async->
appdata + 15 * COAP_TICKS_PER_SECOND);
246 debug(
"check_async: cannot send response for message %d\n",
263 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
264 coap_add_attr(r, (
unsigned char *)
"title", 5, (
unsigned char *)
"\"General Info\"", 14, 0);
275 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
276 coap_add_attr(r, (
unsigned char *)
"title", 5, (
unsigned char *)
"\"Internal Clock\"", 16, 0);
277 coap_add_attr(r, (
unsigned char *)
"rt", 2, (
unsigned char *)
"\"Ticks\"", 7, 0);
279 coap_add_attr(r, (
unsigned char *)
"if", 2, (
unsigned char *)
"\"clock\"", 7, 0);
284 #ifndef WITHOUT_ASYNC
288 coap_add_attr(r, (
unsigned char *)
"ct", 2, (
unsigned char *)
"0", 1, 0);
294 usage(
const char *program,
const char *version) {
297 p = strrchr( program,
'/' );
301 fprintf( stderr,
"%s v%s -- a small CoAP implementation\n"
302 "(c) 2010,2011 Olaf Bergmann <bergmann@tzi.org>\n\n"
303 "usage: %s [-A address] [-p port]\n\n"
304 "\t-A address\tinterface address to bind to\n"
305 "\t-p port\t\tlisten on specified port\n"
306 "\t-v num\t\tverbosity level (default: 3)\n",
307 program, version, program );
314 struct addrinfo hints;
315 struct addrinfo *result, *rp;
317 memset(&hints, 0,
sizeof(
struct addrinfo));
318 hints.ai_family = AF_UNSPEC;
319 hints.ai_socktype = SOCK_DGRAM;
320 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
322 s = getaddrinfo(node, port, &hints, &result);
324 fprintf(stderr,
"getaddrinfo: %s\n", gai_strerror(s));
329 for (rp = result; rp != NULL; rp = rp->ai_next) {
332 if (rp->ai_addrlen <=
sizeof(addr.addr)) {
334 addr.size = rp->ai_addrlen;
335 memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen);
345 fprintf(stderr,
"no context available for interface '%s'\n", node);
348 freeaddrinfo(result);
356 struct timeval tv, *timeout;
360 char addr_str[NI_MAXHOST] =
"::";
361 char port_str[NI_MAXSERV] =
"5683";
365 while ((opt = getopt(argc, argv,
"A:p:v:")) != -1) {
368 strncpy(addr_str, optarg, NI_MAXHOST-1);
369 addr_str[NI_MAXHOST - 1] =
'\0';
372 strncpy(port_str, optarg, NI_MAXSERV-1);
373 port_str[NI_MAXSERV - 1] =
'\0';
376 log_level = strtol(optarg, NULL, 10);
396 FD_SET( ctx->sockfd, &readfds );
408 tv.tv_usec = ((nextpdu->
t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
409 tv.tv_sec = (nextpdu->
t) / COAP_TICKS_PER_SECOND;
416 result = select( FD_SETSIZE, &readfds, 0, 0, timeout );
421 }
else if ( result > 0 ) {
422 if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
428 time_resource->
dirty = 1;
432 #ifndef WITHOUT_ASYNC
437 #ifndef WITHOUT_OBSERVE
unsigned int observe
The next value to be used for Observe.
coap_subscription_t * coap_add_observer(coap_resource_t *resource, const coap_address_t *observer, const str *token)
Adds the specified peer as observer for resource.
int main(int argc, char **argv)
void * appdata
This field can be used to register opaque application data with the asynchronous state object...
void coap_check_notify(coap_context_t *context)
Checks for all known resources, if they are dirty and notifies subscribed observers.
#define COAP_RESPONSE_CODE(N)
void coap_dispatch(coap_context_t *context)
Dispatches the PDUs from the receive queue in given context.
#define COAP_OPTION_CONTENT_FORMAT
#define COAP_RESOURCE_CHECK_TIME
unsigned short length
PDU length (including header, options, data)
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.
#define COAP_OPTION_OBSERVE
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.
void init_resources(coap_context_t *ctx)
#define COAP_OPTION_MAXAGE
static time_t my_clock_base
#define COAP_OPTION_CONTENT_TYPE
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.
coap_queue_t * coap_peek_next(coap_context_t *context)
Returns the next pdu to send without removing from sendqeue.
coap_tick_t sendqueue_basetime
The time stamp in the first element of the sendqeue is relative to sendqueue_basetime.
static coap_async_state_t * async
coap_tick_t t
when to send PDU for the next time
coap_tid_t id
transaction id
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 coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
Header structure for CoAP PDUs.
void hnd_delete_time(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 dirty
set to 1 if resource has changed
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 observable
can be observed
unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val)
Encodes multiple-length byte sequences.
coap_context_t * get_context(const char *node, const char *port)
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
size_t max_size
allocated storage for options and data
void coap_add_resource(coap_context_t *context, coap_resource_t *resource)
Registers the given resource for context.
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)
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
generic resource handling
void hnd_put_time(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_filter_t[(COAP_MAX_OPT >> 3)+1]
Fixed-size bit-vector we use for option filtering.
void check_async(coap_context_t *ctx, coap_tick_t now)
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.
void hnd_get_async(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
void usage(const char *program, const char *version)
#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.
void handle_sigint(int signum)
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...
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.
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...
#define COAP_MEDIATYPE_TEXT_PLAIN
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
unsigned char coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
int coap_read(coap_context_t *ctx)
Reads data from the network and tries to parse as CoAP PDU.
void hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node)
Handles retransmissions of confirmable messages.
coap_queue_t * coap_pop_next(coap_context_t *context)
Returns the next pdu to send and removes it from the sendqeue.
unsigned int non
send non-confirmable notifies if 1
#define COAP_OPT_VALUE(opt)
The CoAP stack's global state is stored in a coap_context_t object.
struct coap_resource_t * time_resource