/* This function creates a set of nodes for testing. These nodes * will exist for all tests and are modified by coap_insert_node() * and */ int t_sendqueue_tests_create(void) { int n, error = 0; sendqueue = NULL; coap_ticks(×tamp[0]); memset(node, 0, sizeof(node)); for (n = 1; n < sizeof(node) / sizeof(coap_queue_t *); n++) { node[n] = coap_new_node(); if (!node[n]) { error = 1; break; } node[n]->id = n; node[n]->t = timestamp[n]; } if (error) { /* destroy all test nodes and set entry to zero */ for (n = 0; n < sizeof(node) / sizeof(coap_queue_t *); n++) { if (node[n]) { coap_delete_node(node[n]); node[n] = NULL; } } } return error; }
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) { coap_tick_t t; size_t size; unsigned char *data; /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0 * and request is empty. When not empty, set to value in request payload * (insist on query ?ticks). Return Created or Ok. */ /* if my_clock_base was deleted, we pretend to have no such resource */ response->hdr->code = my_clock_base ? COAP_RESPONSE_CODE(204) : COAP_RESPONSE_CODE(201); resource->dirty = 1; coap_get_data(request, &size, &data); if (size == 0) /* re-init */ my_clock_base = clock_offset; else { my_clock_base = 0; coap_ticks(&t); while(size--) my_clock_base = my_clock_base * 10 + *data++; my_clock_base -= t / COAP_TICKS_PER_SECOND; } }
void t_sendqueue6(void) { unsigned int result; coap_tick_t now; const coap_tick_diff_t delta = 20; struct coap_context_t ctx; /* space for saving the current node timestamps */ static coap_tick_t times[sizeof(timestamp) / sizeof(coap_tick_t)]; coap_queue_t *p; int i; /* save timestamps of nodes in the sendqueue in their actual order */ memset(times, 0, sizeof(times)); for (p = sendqueue, i = 0; p; p = p->next, i++) { times[i] = p->t; } coap_ticks(&now); ctx.sendqueue = NULL; ctx.sendqueue_basetime = now; result = coap_adjust_basetime(&ctx, now + delta); CU_ASSERT(result == 0); CU_ASSERT(ctx.sendqueue_basetime == now + delta); /* restore timestamps of nodes in the sendqueue */ for (p = sendqueue, i = 0; p; p = p->next, i++) { p->t = times[i]; } }
int coap_cmd(int argc, char **argv) { coap_context_t *ctx; struct timeval tv, *timeout; coap_tick_t now; coap_queue_t *nextpdu; coap_log_t log_level = LOG_WARNING; coap_set_log_level(log_level); ctx = get_context(); if (!ctx) return -1; init_resources(ctx); while ( !quit ) { nextpdu = coap_peek_next( ctx ); coap_ticks(&now); while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { coap_retransmit( ctx, coap_pop_next( ctx ) ); nextpdu = coap_peek_next( ctx ); } if ( nextpdu && nextpdu->t <= COAP_RESOURCE_CHECK_TIME ) { /* set timeout if there is a pdu to send before our automatic timeout occurs */ tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; timeout = &tv; } else { tv.tv_usec = 0; tv.tv_sec = COAP_RESOURCE_CHECK_TIME; timeout = &tv; } (void) timeout; coap_read(ctx); /* read received data */ coap_dispatch(ctx); /* and dispatch PDUs from receivequeue */ #ifndef WITHOUT_ASYNC /* check if we have to send asynchronous responses */ check_async(ctx, now); #endif /* WITHOUT_ASYNC */ #ifndef WITHOUT_OBSERVE /* check if we have to send observe notifications */ coap_check_notify(ctx); #endif /* WITHOUT_OBSERVE */ } coap_free_context( ctx ); return 0; }
void t_sendqueue5(void) { const coap_tick_diff_t delta1 = 20, delta2 = 130; unsigned int result; coap_tick_t now; struct coap_context_t ctx; /* space for saving the current node timestamps */ static coap_tick_t times[sizeof(timestamp) / sizeof(coap_tick_t)]; coap_queue_t *p; int i; /* save timestamps of nodes in the sendqueue in their actual order */ memset(times, 0, sizeof(times)); for (p = sendqueue, i = 0; p; p = p->next, i++) { times[i] = p->t; } coap_ticks(&now); ctx.sendqueue = sendqueue; ctx.sendqueue_basetime = now; now -= delta1; result = coap_adjust_basetime(&ctx, now); CU_ASSERT(result == 0); CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue); CU_ASSERT(ctx.sendqueue_basetime == now); CU_ASSERT(ctx.sendqueue->t == timestamp[3] + delta1); now += delta2; result = coap_adjust_basetime(&ctx, now); CU_ASSERT(result == 2); CU_ASSERT(ctx.sendqueue_basetime == now); CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue); CU_ASSERT(ctx.sendqueue->t == 0); CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next); CU_ASSERT(ctx.sendqueue->next->t == 0); CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next->next); CU_ASSERT(ctx.sendqueue->next->next->t == delta2 - delta1 - timestamp[1]); /* restore timestamps of nodes in the sendqueue */ for (p = sendqueue, i = 0; p; p = p->next, i++) { p->t = times[i]; } }
/* * This function checks if the node is past its time to live and * deletes it if timed-out. Calling this function with a presence or observe * callback with ttl set to 0 will not delete anything as presence nodes have * their own mechanisms for timeouts. A null argument will cause the function to * silently return. */ static void CheckAndDeleteTimedOutCB(ClientCB* cbNode) { if (!cbNode) { return; } if (cbNode->TTL == 0) { return; } coap_tick_t now; coap_ticks(&now); if (cbNode->TTL < now) { OC_LOG(INFO, TAG, "Deleting timed-out callback"); DeleteClientCB(cbNode); } }
int CoAPWrapper::time_out(ACE_Time_Value& tm) { struct timeval tv, *timeout; int result; coap_tick_t now; coap_queue_t *nextpdu; coap_context_t *ctx; if (coap_ctx_ == 0 ) return 0; ctx = coap_ctx_; nextpdu = coap_peek_next( ctx ); coap_ticks(&now); while ( nextpdu && nextpdu->t <= now ) { coap_retransmit( ctx, coap_pop_next( ctx ) ); nextpdu = coap_peek_next( ctx ); } if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME ) { /* set timeout if there is a pdu to send before our automatic timeout occurs */ tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; timeout = &tv; } else { tv.tv_usec = 0; tv.tv_sec = COAP_RESOURCE_CHECK_TIME; timeout = &tv; } tm.set(*timeout); return 0; }
uint32_t GetTime(float afterSeconds) { coap_tick_t now; coap_ticks(&now); return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND); }
int main(int argc, char **argv) { coap_context_t *ctx; fd_set readfds; struct timeval tv, *timeout; int result; coap_tick_t now; coap_queue_t *nextpdu; char addr_str[NI_MAXHOST] = "::"; char port_str[NI_MAXSERV] = "5683"; int opt; coap_log_t log_level = LOG_WARN; while ((opt = getopt(argc, argv, "A:p:v:")) != -1) { switch (opt) { case 'A' : strncpy(addr_str, optarg, NI_MAXHOST-1); addr_str[NI_MAXHOST - 1] = '\0'; break; case 'p' : strncpy(port_str, optarg, NI_MAXSERV-1); port_str[NI_MAXSERV - 1] = '\0'; break; case 'v' : log_level = strtol(optarg, NULL, 10); break; default: usage( argv[0], PACKAGE_VERSION ); exit( 1 ); } } coap_set_log_level(log_level); ctx = get_context(addr_str, port_str); if (!ctx) return -1; coap_register_option(ctx, COAP_OPTION_BLOCK2); init_resources(ctx); signal(SIGINT, handle_sigint); while ( !quit ) { FD_ZERO(&readfds); FD_SET( ctx->sockfd, &readfds ); nextpdu = coap_peek_next( ctx ); coap_ticks(&now); while ( nextpdu && nextpdu->t <= now ) { coap_retransmit( ctx, coap_pop_next( ctx ) ); nextpdu = coap_peek_next( ctx ); } if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME_SEC ) { /* set timeout if there is a pdu to send before our automatic timeout occurs */ tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND; timeout = &tv; } else { tv.tv_usec = 0; tv.tv_sec = COAP_RESOURCE_CHECK_TIME_SEC; timeout = &tv; } result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); if ( result < 0 ) { /* error */ if (errno != EINTR) perror("select"); } else if ( result > 0 ) { /* read from socket */ if ( FD_ISSET( ctx->sockfd, &readfds ) ) { coap_read( ctx ); /* read received data */ coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */ } } else { /* timeout */ /* coap_check_resource_list( ctx ); */ } /* check if we have to send asynchronous responses */ check_async(ctx, now); } coap_free_context( ctx ); return 0; }
void hnd_post_rd(coap_context_t *ctx, struct coap_resource_t *resource, const coap_endpoint_t *local_interface, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response) { size_t len=0; unsigned char *databuf; unsigned char strBuf[100]; unsigned char s[100]; coap_print_addr(peer, s, 100); if (coap_get_data(request, &len, &databuf)){ memcpy(strBuf, databuf, len); strBuf[len]='\0'; fprintf(stdout, "%s %s\n", s, strBuf); }else{ fprintf(stdout, "%s\n", s); } fflush(stdout); coap_resource_t *r; coap_opt_iterator_t opt_iter; coap_opt_t *query; #define LOCSIZE 68 unsigned char *loc; size_t loc_size; str h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */ unsigned char *buf; loc = (unsigned char *)coap_malloc(LOCSIZE); if (!loc) { response->hdr->code = COAP_RESPONSE_CODE(500); return; } memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE); loc_size = RD_ROOT_SIZE; loc[loc_size++] = '/'; /* store query parameters for later use */ query = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter); if (query) { parse_param((unsigned char *)"h", 1, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &h); parse_param((unsigned char *)"ins", 3, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &ins); parse_param((unsigned char *)"lt", 2, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), <); parse_param((unsigned char *)"rt", 2, COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &rt); } if (h.length) { /* client has specified a node name */ memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1)); loc_size += min(h.length, LOCSIZE - loc_size - 1); if (ins.length && loc_size > 1) { loc[loc_size++] = '-'; memcpy((char *)(loc + loc_size), ins.s, min(ins.length, LOCSIZE - loc_size - 1)); loc_size += min(ins.length, LOCSIZE - loc_size - 1); } } else { /* generate node identifier */ loc_size += snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, "%x", request->hdr->id); if (loc_size > 1) { if (ins.length) { loc[loc_size++] = '-'; memcpy((char *)(loc + loc_size), ins.s, min(ins.length, LOCSIZE - loc_size - 1)); loc_size += min(ins.length, LOCSIZE - loc_size - 1); } else { coap_tick_t now; coap_ticks(&now); loc_size += snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1, "-%x", now); } } } /* TODO: * - use lt to check expiration */ r = coap_resource_init(loc, loc_size, COAP_RESOURCE_FLAGS_RELEASE_URI); coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource); coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_resource); coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource); if (ins.s) { buf = (unsigned char *)coap_malloc(ins.length + 2); if (buf) { /* add missing quotes */ buf[0] = '"'; memcpy(buf + 1, ins.s, ins.length); buf[ins.length + 1] = '"'; coap_add_attr(r, (unsigned char *)"ins", 3, buf, ins.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE); } } if (rt.s) { buf = (unsigned char *)coap_malloc(rt.length + 2); if (buf) { /* add missing quotes */ buf[0] = '"'; memcpy(buf + 1, rt.s, rt.length); buf[rt.length + 1] = '"'; coap_add_attr(r, (unsigned char *)"rt", 2, buf, rt.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE); } } add_source_address(r, peer); { rd_t *rd; rd = make_rd(peer, request); if (rd) { coap_hash_path(loc, loc_size, rd->key); HASH_ADD(hh, resources, key, sizeof(coap_key_t), rd); } else { /* FIXME: send error response and delete r */ } } coap_add_resource(ctx, r); /* create response */ response->hdr->code = COAP_RESPONSE_CODE(201); { /* split path into segments and add Location-Path options */ unsigned char _b[LOCSIZE]; unsigned char *b = _b; size_t buflen = sizeof(_b); int nseg; nseg = coap_split_path(loc, loc_size, b, &buflen); while (nseg--) { coap_add_option(response, COAP_OPTION_LOCATION_PATH, COAP_OPT_LENGTH(b), COAP_OPT_VALUE(b)); b += COAP_OPT_SIZE(b); } } }
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_opt_iterator_t opt_iter; coap_opt_t *option; unsigned char buf[40]; size_t len; time_t now; coap_tick_t t; coap_subscription_t *subscription; /* FIXME: return time, e.g. in human-readable by default and ticks * when query ?ticks is given. */ /* if my_clock_base was deleted, we pretend to have no such resource */ response->hdr->code = my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404); if (request != NULL && coap_check_option(request, COAP_OPTION_OBSERVE, &opt_iter)) { subscription = coap_add_observer(resource, peer, token); if (subscription) { subscription->non = request->hdr->type == COAP_MESSAGE_NON; coap_add_option(response, COAP_OPTION_OBSERVE, 0, NULL); } } if (resource->dirty == 1) coap_add_option(response, COAP_OPTION_OBSERVE, coap_encode_var_bytes(buf, ctx->observe), buf); if (my_clock_base) coap_add_option(response, COAP_OPTION_CONTENT_FORMAT, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x01), buf); if (my_clock_base) { /* calculate current time */ coap_ticks(&t); now = my_clock_base + (t / COAP_TICKS_PER_SECOND); if (request != NULL && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter)) && memcmp(COAP_OPT_VALUE(option), "ticks", min(5, COAP_OPT_LENGTH(option))) == 0) { /* output ticks */ len = snprintf((char *)buf, min(sizeof(buf), response->max_size - response->length), "%u", (unsigned int)now); coap_add_data(response, len, buf); } else { /* output human-readable time */ struct tm *tmp; tmp = gmtime(&now); len = strftime((char *)buf, min(sizeof(buf), response->max_size - response->length), "%b %d %H:%M:%S", tmp); coap_add_data(response, len, buf); } } }