Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
client_dtls.c
00001 #include <stdio.h> 00002 #include <string.h> 00003 #include <errno.h> 00004 #include <unistd.h> 00005 #include <ctype.h> 00006 #include <netinet/in.h> 00007 #include <sys/types.h> 00008 #include <sys/socket.h> 00009 #include <sys/time.h> 00010 #include <arpa/inet.h> 00011 #include <netdb.h> 00012 00013 #include <stdlib.h> 00014 #include <time.h> 00015 00016 #include "coap.h" 00017 #include "dtls.h" 00018 00019 #define COAPS_SRV "173.255.243.158" 00020 #define COAPS_SRV_PORT 20220 00021 00022 #define BUFSIZE 2048 00023 #define MAX_DOWNLOAD_SIZE 102400 // 100k 00024 #define MAX_RETRY 3 00025 #define TIMEOUT 5 00026 00027 #define PRINTF(...) printf(__VA_ARGS__);fflush(stdout); 00028 00029 #define TEST_READ 0x02 00030 #define TEST_WRITE 0x04 00031 #define TEST_UPLOAD_FILE 0x08 00032 #define TEST_ACTIVATE 0x10 00033 #define TEST_DOWNLOAD_CONTENT 0x20 00034 00035 #define block_size 5 // Range: 1 - 6 00036 00037 void hex_dump(uint8_t* bytes, size_t len); 00038 void coap_pretty_print(uint8_t* pkt, size_t len); 00039 00040 int main(void) 00041 { 00042 char alias[] = "temp"; 00043 char cik[] = "a32c85ba9dda45823be416246cf8b433baa068d7"; 00044 00045 char host[] = "coap.exosite.com"; 00046 char port[] = "5683"; 00047 00048 srand(time(NULL)); 00049 00050 // CoAP Message Setup 00051 #define MSG_BUF_LEN 64 00052 uint8_t msg_send[MSG_BUF_LEN]; 00053 size_t msg_send_len = 0; 00054 uint8_t msg_recv[MSG_BUF_LEN]; 00055 size_t msg_recv_len = 0; 00056 00057 uint16_t message_id_counter = rand(); 00058 00059 // Socket to Exosite 00060 int localsock, remotesock; 00061 size_t bytes_sent; 00062 int rv; 00063 00064 struct addrinfo exohints, *servinfo, *p, *q; 00065 00066 memset(&exohints, 0, sizeof exohints); 00067 exohints.ai_family = AF_UNSPEC; 00068 exohints.ai_socktype = SOCK_DGRAM; 00069 exohints.ai_flags = AI_PASSIVE; 00070 00071 if ((rv = getaddrinfo(NULL, port, &exohints, &servinfo)) != 0) { 00072 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 00073 return 1; 00074 } 00075 00076 // loop through all the results and make a socket 00077 for(p = servinfo; p != NULL; p = p->ai_next) { 00078 if ((localsock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { 00079 perror("bad socket"); 00080 continue; 00081 } 00082 00083 if (bind(localsock, p->ai_addr, p->ai_addrlen) == -1) { 00084 close(localsock); 00085 perror("bad bind"); 00086 continue; 00087 } 00088 00089 break; 00090 } 00091 00092 if (p == NULL) { 00093 fprintf(stderr, "Failed to Bind Socket\n"); 00094 return 2; 00095 } 00096 00097 if ((rv = getaddrinfo(host, port, &exohints, &servinfo)) != 0) { 00098 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 00099 return 1; 00100 } 00101 00102 00103 // loop through all the results and make a socket 00104 for(q = servinfo; q != NULL; q = q->ai_next) { 00105 if ((remotesock = socket(q->ai_family, q->ai_socktype, q->ai_protocol)) == -1) { 00106 perror("bad socket"); 00107 continue; 00108 } 00109 00110 break; 00111 } 00112 00113 if (q == NULL) { 00114 fprintf(stderr, "Failed to Bind Socket\n"); 00115 return 2; 00116 } 00117 00118 for (;;) 00119 { 00120 printf("--------------------------------------------------------------------------------\n"); 00121 00122 // Build Message 00123 msg_send_len = 0; // Clear Message Buffer 00124 memset(msg_send, 0, msg_send_len); 00125 coap_set_version(msg_send, &msg_send_len, MSG_BUF_LEN, COAP_V1); 00126 coap_set_type(msg_send, &msg_send_len, MSG_BUF_LEN, CT_CON); 00127 coap_set_code(msg_send, &msg_send_len, MSG_BUF_LEN, CC_GET); //or POST 00128 coap_set_mid(msg_send, &msg_send_len, MSG_BUF_LEN, message_id_counter++); 00129 coap_set_token(msg_send, &msg_send_len, MSG_BUF_LEN, rand(), 2); 00130 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)"1a", 2); 00131 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)alias, strlen(alias)); 00132 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_QUERY, (uint8_t*)cik, strlen(cik)); 00133 //coap_set_payload(msg_send, &msg_send_len, MSG_BUF_LEN, (uint8_t*)"99", 2); 00134 00135 // Send Message 00136 if ((bytes_sent = sendto(remotesock, msg_send, msg_send_len, 0, q->ai_addr, q->ai_addrlen)) == -1){ 00137 fprintf(stderr, "Failed to Send Message\n"); 00138 return 2; 00139 } 00140 00141 printf("Sent.\n"); 00142 coap_pretty_print(msg_send, msg_send_len); 00143 00144 // Wait for Response 00145 msg_recv_len = recvfrom(remotesock, (void *)msg_recv, sizeof(msg_recv), 0, q->ai_addr, &q->ai_addrlen); 00146 if (msg_recv_len < 0) { 00147 fprintf(stderr, "%s\n", strerror(errno)); 00148 exit(EXIT_FAILURE); 00149 } 00150 00151 00152 if(coap_validate_pkt(msg_recv, msg_recv_len) == CS_OK) 00153 { 00154 printf("Got Valid CoAP Packet\n"); 00155 if(coap_get_mid(msg_recv, msg_recv_len) == coap_get_mid(msg_send, msg_send_len) && 00156 coap_get_token(msg_recv, msg_recv_len, 0) == coap_get_token(msg_send, msg_send_len, 0)) //this is only actually checking token length, should check token. 00157 { 00158 printf("Is Response to Last Message\n"); 00159 coap_pretty_print(msg_recv, msg_recv_len); 00160 } 00161 }else{ 00162 printf("Received %zi Bytes, Not Valid CoAP\n", msg_recv_len); 00163 hex_dump(msg_recv, msg_recv_len); 00164 } 00165 00166 usleep(1000000); // One Second 00167 } 00168 } 00169 00170 // TEST_READ , TEST_WRITE 00171 static char alias[] = "temp"; 00172 static char cik[] = "a32c85ba9dda45823be416246cf8b433baa068d7"; 00173 static char value_to_write[] = "56"; 00174 00175 // dtls setup 00176 static size_t dtls_connected = 0; 00177 static size_t ready_to_recv = 0; 00178 static dtls_context_t *dtls_context = NULL; 00179 static session_t session; 00180 00181 typedef struct trans_data { 00182 int out; 00183 int ack; 00184 uint8* data; 00185 int retry; 00186 } trans_data; 00187 00188 struct trans_data last_sent = {.retry=0}; 00189 00190 #define SET_SEND_TIMESTAMP() {last_sent.out = (int)time(NULL); \ 00191 last_sent.data = (uint8*)sent_pdu->hdr; \ 00192 last_sent.ack = 0; \ 00193 last_sent.retry++;} 00194 #define SET_ACK_TIMESTAMP() {last_sent.ack = (int)time(NULL); last_sent.retry = 0;} 00195 00196 int order_opts(void *a, void *b) 00197 { 00198 if (!a || !b) 00199 return a < b ? -1 : 1; 00200 00201 if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option *)b)) 00202 return -1; 00203 00204 return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option *)b); 00205 } 00206 00207 coap_pdu_t* coap_new_request(coap_context_t *ctx, unsigned char method, coap_list_t *options, str payload ) 00208 { 00209 coap_pdu_t *pdu; 00210 coap_list_t *opt; 00211 00212 if ( ! ( pdu = coap_new_pdu() ) ) 00213 return NULL; 00214 00215 pdu->hdr->type = COAP_MESSAGE_CON; 00216 pdu->hdr->id = coap_new_message_id(ctx); 00217 pdu->hdr->code = method; 00218 pdu->hdr->token_length = the_token.length; 00219 if ( !coap_add_token(pdu, the_token.length, the_token.s)) { 00220 debug("cannot add token to request\n"); 00221 } 00222 for (opt = options; opt; opt = opt->next) { 00223 coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data), 00224 COAP_OPTION_LENGTH(*(coap_option *)opt->data), 00225 COAP_OPTION_DATA(*(coap_option *)opt->data)); 00226 } 00227 if (payload.length) { 00228 if (block_flag) 00229 coap_add_block(pdu, payload.length, payload.s, block.num, block.szx); 00230 else 00231 coap_add_data(pdu, payload.length, payload.s); 00232 } 00233 00234 //coap_show_pdu(pdu); 00235 00236 return pdu; 00237 } 00238 00239 coap_list_t* new_option_node(unsigned short key, unsigned int length, unsigned char *data) 00240 { 00241 coap_option *option; 00242 coap_list_t *node; 00243 00244 option = coap_malloc(sizeof(coap_option) + length); 00245 if ( !option ) 00246 goto error; 00247 00248 COAP_OPTION_KEY(*option) = key; 00249 COAP_OPTION_LENGTH(*option) = length; 00250 memcpy(COAP_OPTION_DATA(*option), data, length); 00251 /* we can pass NULL here as delete function since option is released automatically */ 00252 node = coap_new_listnode(option, NULL); 00253 00254 if ( node ) 00255 return node; 00256 00257 error: 00258 perror("new_option_node: malloc"); 00259 coap_free( option ); 00260 return NULL; 00261 } 00262 00263 coap_context_t* get_context(const char *node, const char *port) 00264 { 00265 coap_context_t *ctx = NULL; 00266 int s; 00267 struct addrinfo hints; 00268 struct addrinfo *result, *rp; 00269 00270 memset(&hints, 0, sizeof(struct addrinfo)); 00271 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 00272 hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ 00273 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL; 00274 00275 s = getaddrinfo(node, port, &hints, &result); 00276 if ( s != 0 ) { 00277 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); 00278 return NULL; 00279 } 00280 /* iterate through results until success */ 00281 for (rp = result; rp != NULL; rp = rp->ai_next) { 00282 coap_address_t addr; 00283 if (rp->ai_addrlen <= sizeof(addr.addr)) { 00284 coap_address_init(&addr); 00285 addr.size = rp->ai_addrlen; 00286 memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); 00287 00288 ctx = coap_new_context(&addr); 00289 if (ctx) { 00290 goto finish; 00291 } 00292 } 00293 } 00294 00295 fprintf(stderr, "no context available for interface '%s'\n", node); 00296 00297 finish: 00298 freeaddrinfo(result); 00299 return ctx; 00300 } 00301 00302 coap_pdu_t* get_pdu(char* url, unsigned char method, str payload) 00303 { 00304 coap_pdu_t *pdu; 00305 size_t buflen; 00306 int res; 00307 optlist=NULL; 00308 00309 coap_split_uri((unsigned char *)url, strlen(url), &uri ); 00310 if (uri.path.length) { 00311 buflen = BUFSIZE; 00312 unsigned char _buf[BUFSIZE]; 00313 unsigned char *buf = _buf; 00314 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); 00315 while (res--) { 00316 coap_insert(&optlist, 00317 new_option_node( 00318 COAP_OPTION_URI_PATH, 00319 COAP_OPT_LENGTH(buf), 00320 COAP_OPT_VALUE(buf)), 00321 order_opts); 00322 buf += COAP_OPT_SIZE(buf); 00323 } 00324 } 00325 if (uri.query.length) { 00326 buflen = BUFSIZE; 00327 unsigned char _buf[BUFSIZE]; 00328 unsigned char *buf = _buf; 00329 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); 00330 while (res--) { 00331 coap_insert(&optlist, 00332 new_option_node( 00333 COAP_OPTION_URI_QUERY, 00334 COAP_OPT_LENGTH(buf), 00335 COAP_OPT_VALUE(buf)), 00336 order_opts); 00337 buf += COAP_OPT_SIZE(buf); 00338 } 00339 } 00340 if (NULL == coap_ctx) 00341 coap_ctx = get_context("0.0.0.0", "0"); 00342 00343 if (block_flag) { 00344 static unsigned char tmp[4]; 00345 unsigned short opt; 00346 opt = method == COAP_REQUEST_GET ? COAP_OPTION_BLOCK2 : COAP_OPTION_BLOCK1; 00347 char more; 00348 if (coap_more_blocks(payload.length, block.num, block.szx)) 00349 more = 0x08; 00350 else 00351 more = 0x00; 00352 //printf(" more:%d block num:%d\n", more, block.num); 00353 coap_insert(&optlist, 00354 new_option_node( 00355 opt, 00356 coap_encode_var_bytes(tmp, (block.num << 4 | block.szx | more)), 00357 tmp), 00358 order_opts); 00359 } 00360 if (! (pdu = coap_new_request(coap_ctx, method, optlist, payload))) 00361 return NULL; 00362 return pdu; 00363 00364 } 00365 00366 coap_pdu_t* get_pdu_activate(char* vendor, char* model, char* serial_number) 00367 { 00368 char dest[BUFSIZE]; 00369 strcpy(dest, "coap://0.0.0.0/provision/activate/"); //address is virtual 00370 strcat(dest, vendor); 00371 strcat(dest, "/"); 00372 strcat(dest, model); 00373 strcat(dest, "/"); 00374 strcat(dest, serial_number); 00375 str payload = { 0, NULL }; 00376 return get_pdu(dest, COAP_REQUEST_POST, payload); 00377 00378 00379 msg_send_len = 0; // Clear Message Buffer 00380 memset(msg_send, 0, msg_send_len); 00381 coap_set_version(msg_send, &msg_send_len, MSG_BUF_LEN, COAP_V1); 00382 coap_set_type(msg_send, &msg_send_len, MSG_BUF_LEN, CT_CON); 00383 coap_set_code(msg_send, &msg_send_len, MSG_BUF_LEN, CC_POST); 00384 coap_set_mid(msg_send, &msg_send_len, MSG_BUF_LEN, message_id_counter++); 00385 coap_set_token(msg_send, &msg_send_len, MSG_BUF_LEN, rand(), 2); 00386 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)"provision", 9); 00387 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)"activate", 8); 00388 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)vendor, strlen(vendor)); 00389 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)model, strlen(model)); 00390 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)serial_number, strlen(serial_number)); 00391 } 00392 00393 coap_pdu_t* get_pdu_download_content() 00394 { 00395 char dest[BUFSIZE]; 00396 strcpy(dest, "coap://0.0.0.0/provision/download/"); //address is virtual 00397 strcat(dest, vendor); 00398 strcat(dest, "/"); 00399 strcat(dest, model); 00400 strcat(dest, "/"); 00401 strcat(dest, content_id); 00402 strcat(dest, "?"); 00403 strcat(dest, client_model_cik); 00404 str payload = { 0, NULL }; 00405 block_flag = 1; 00406 return get_pdu(dest, COAP_REQUEST_GET, payload); 00407 00408 msg_send_len = 0; // Clear Message Buffer 00409 memset(msg_send, 0, msg_send_len); 00410 coap_set_version(msg_send, &msg_send_len, MSG_BUF_LEN, COAP_V1); 00411 coap_set_type(msg_send, &msg_send_len, MSG_BUF_LEN, CT_CON); 00412 coap_set_code(msg_send, &msg_send_len, MSG_BUF_LEN, CC_POST); 00413 coap_set_mid(msg_send, &msg_send_len, MSG_BUF_LEN, message_id_counter++); 00414 coap_set_token(msg_send, &msg_send_len, MSG_BUF_LEN, rand(), 2); 00415 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)"provision", 9); 00416 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)"download", 8); 00417 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)vendor, strlen(vendor)); 00418 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)model, strlen(model)); 00419 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)serial_number, strlen(serial_number)); 00420 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_PATH, (uint8_t*)alias, strlen(alias)); 00421 coap_add_option(msg_send, &msg_send_len, MSG_BUF_LEN, CON_URI_QUERY, (uint8_t*)cik, strlen(cik)); 00422 00423 return EXO_OK; 00424 } 00425 00426 coap_pdu_t* get_pdu_read1p(char* cik, char* alias) 00427 { 00428 char dest[BUFSIZE]; 00429 strcpy(dest, "coap://0.0.0.0/1a/"); //address is virtual 00430 strcat(dest, alias); 00431 strcat(dest, "?"); 00432 strcat(dest, cik); 00433 str payload = { 0, NULL }; 00434 return get_pdu(dest, COAP_REQUEST_GET, payload); 00435 } 00436 00437 coap_pdu_t* get_pdu_write1p(char* cik, char* alias, char* value) 00438 { 00439 char dest[BUFSIZE]; 00440 strcpy(dest, "coap://0.0.0.0/1a/"); //address is virtual 00441 strcat(dest, alias); 00442 strcat(dest, "?"); 00443 strcat(dest, cik); 00444 str payload = { strlen(value), (unsigned char*)value }; 00445 return get_pdu(dest, COAP_REQUEST_POST, payload); 00446 } 00447 00448 coap_pdu_t* get_pdu_block_upload(char* cik, char* alias, int length, unsigned char* data) 00449 { 00450 char dest[BUFSIZE]; 00451 strcpy(dest, "coap://0.0.0.0/1a/"); //address is virtual 00452 strcat(dest, alias); 00453 strcat(dest, "?"); 00454 strcat(dest, cik); 00455 str payload = { length, data }; 00456 block_flag = 1; 00457 return get_pdu(dest, COAP_REQUEST_PUT, payload); 00458 } 00459 00460 static inline coap_opt_t * get_block(coap_pdu_t *pdu, coap_opt_iterator_t *opt_iter) 00461 { 00462 coap_opt_filter_t f; 00463 00464 assert(pdu); 00465 memset(f, 0, sizeof(coap_opt_filter_t)); 00466 coap_option_setb(f, COAP_OPTION_BLOCK1); 00467 coap_option_setb(f, COAP_OPTION_BLOCK2); 00468 00469 coap_option_iterator_init(pdu, opt_iter, f); 00470 return coap_option_next(opt_iter); 00471 } 00472 00473 inline int check_token(coap_pdu_t *received) 00474 { 00475 return received->hdr->token_length == the_token.length && 00476 memcmp(received->hdr->token, the_token.s, the_token.length) == 0; 00477 } 00478 00479 void message_handler(coap_pdu_t *received) 00480 { 00481 size_t len; 00482 unsigned char *databuf = NULL; 00483 coap_opt_t *block_opt; 00484 coap_opt_iterator_t opt_iter; 00485 00486 PRINTF("Receive %d.%02d response.\n\n", 00487 (received->hdr->code >> 5), received->hdr->code & 0x1F); 00488 /* check if this is a response to our original request */ 00489 if (!check_token(received)) { 00490 return; 00491 } 00492 00493 coap_get_data(received, &len, &databuf); 00494 block_opt = get_block(received, &opt_iter); 00495 coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter); 00496 00497 if ( received->hdr->code == COAP_RESPONSE_CODE(205) ) { 00498 if (block_opt) { // block option 00499 download_size += len; 00500 if (COAP_OPT_BLOCK_MORE(block_opt)) { // has more 00501 PRINTF("found the M bit, block size is %u, block nr. %u\n", 00502 COAP_OPT_BLOCK_SZX(block_opt), coap_opt_block_num(block_opt)); 00503 strcat(download_content, (char*)databuf); 00504 SET_ACK_TIMESTAMP(); 00505 block.num += 1; 00506 sent_pdu = get_pdu_download_content(vendor, model, content_id); 00507 dtls_write(dtls_context, &session, (uint8*)sent_pdu->hdr, sent_pdu->length); 00508 SET_SEND_TIMESTAMP(); 00509 } else { 00510 strcat(download_content, (char*)databuf); 00511 FILE *fp; 00512 fp=fopen(download_save_file, "wb"); 00513 fwrite(download_content, 1, download_size, fp); 00514 fclose(fp); 00515 PRINTF("Downloaded content is saved to file '%s'.\n", download_save_file); 00516 ready_to_recv = 0; 00517 } 00518 } else { // no block option 00519 if (databuf) 00520 PRINTF("payload: '%s'\n", databuf); 00521 ready_to_recv = 0; 00522 return; 00523 } 00524 } else if ( received->hdr->code == COAP_RESPONSE_CODE(204)) { 00525 if (databuf) 00526 PRINTF("payload: '%s'\n", databuf); 00527 ready_to_recv = 0; 00528 } else { // other than 2.05, 2.04// 00529 if (block_opt && received->hdr->code == COAP_RESPONSE_CODE(231)) { // block option 00530 if (COAP_OPT_BLOCK_MORE(block_opt)) { // has more 00531 PRINTF("found the M bit, block size is %u, block nr. %u\n", 00532 COAP_OPT_BLOCK_SZX(block_opt), coap_opt_block_num(block_opt)); 00533 SET_ACK_TIMESTAMP(); 00534 block.num += 1; 00535 sent_pdu = get_pdu_block_upload(cik, alias, file_size, file_data); 00536 dtls_write(dtls_context, &session, (uint8*)sent_pdu->hdr, sent_pdu->length); 00537 SET_SEND_TIMESTAMP(); 00538 } 00539 } else { //not block option 00540 if (databuf) 00541 PRINTF("payload: '%s'\n", databuf); 00542 ready_to_recv = 0; 00543 } 00544 } 00545 } 00546 00547 /* This function is the "key store" for tinyDTLS. It is called to 00548 * retrieve a key for the given identiy within this particular 00549 * session. */ 00550 int get_key(struct dtls_context_t *ctx, 00551 const session_t *session, 00552 const unsigned char *id, size_t id_len, 00553 const dtls_key_t **result) 00554 { 00555 static const dtls_key_t psk = { 00556 .type = DTLS_KEY_PSK, 00557 .key.psk.id = (unsigned char *)"Client_identity", 00558 .key.psk.id_length = 15, 00559 .key.psk.key = (unsigned char *)"ex0CoAPs", 00560 .key.psk.key_length = 9 00561 }; 00562 *result = &psk; 00563 return 0; 00564 } 00565 00566 int handle_event(struct dtls_context_t *ctx, session_t *session, 00567 dtls_alert_level_t level, unsigned short code) 00568 { 00569 if (code == DTLS_EVENT_CONNECTED) 00570 dtls_connected = 1; 00571 return 0; 00572 } 00573 00574 int read_from_server(struct dtls_context_t *ctx, 00575 session_t *session, uint8 *data, size_t len) 00576 { 00577 //printf ("Server message:\n"); 00578 //size_t i; 00579 //for (i = 0; i < len; i++) 00580 // printf("%02x ", data[i]); 00581 //printf("\n"); 00582 coap_pdu_t* received_pdu = coap_new_pdu(); 00583 if (coap_pdu_parse(data, len, received_pdu)) { 00584 message_handler(received_pdu); 00585 } else 00586 PRINTF("Invalid CoAP message!"); 00587 00588 return 0; 00589 } 00590 00591 int send_to_peer(struct dtls_context_t *ctx, 00592 session_t *session, uint8 *data, size_t len) 00593 { 00594 int fd = *(int *)dtls_get_app_data(ctx); 00595 return sendto(fd, data, len, MSG_DONTWAIT, 00596 &session->addr.sa, session->size); 00597 } 00598 00599 int dtls_handle_read(struct dtls_context_t *ctx) 00600 { 00601 int fd; 00602 session_t session; 00603 static uint8 buf[BUFSIZE]; 00604 int len; 00605 00606 fd = *(int *)dtls_get_app_data(ctx); 00607 00608 if (!fd) 00609 return -1; 00610 00611 memset(&session, 0, sizeof(session_t)); 00612 session.size = sizeof(session.addr); 00613 len = recvfrom(fd, buf, BUFSIZE, 0, 00614 &session.addr.sa, &session.size); 00615 if (len < 0) { 00616 perror("recvfrom"); 00617 return -1; 00618 } else { 00619 } 00620 return dtls_handle_message(ctx, &session, buf, len); 00621 } 00622 00623 int resolve_address(const char *server, struct sockaddr *dst) 00624 { 00625 struct addrinfo *res, *ainfo; 00626 struct addrinfo hints; 00627 static char addrstr[256]; 00628 int error; 00629 00630 memset(addrstr, 0, sizeof(addrstr)); 00631 if (server && strlen(server) > 0) 00632 memcpy(addrstr, server, strlen(server)); 00633 else 00634 memcpy(addrstr, "localhost", 9); 00635 00636 memset ((char *)&hints, 0, sizeof(hints)); 00637 hints.ai_socktype = SOCK_DGRAM; 00638 hints.ai_family = AF_UNSPEC; 00639 00640 error = getaddrinfo(addrstr, "", &hints, &res); 00641 00642 if (error != 0) { 00643 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); 00644 return error; 00645 } 00646 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) { 00647 00648 switch (ainfo->ai_family) { 00649 case AF_INET6: 00650 case AF_INET: 00651 memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen); 00652 return ainfo->ai_addrlen; 00653 default: 00654 ; 00655 } 00656 } 00657 freeaddrinfo(res); 00658 return -1; 00659 } 00660 00661 /*---------------------------------------------------------------------------*/ 00662 00663 static dtls_handler_t cb = { 00664 .write = send_to_peer, 00665 .read = read_from_server, 00666 .event = handle_event, 00667 .get_key = get_key 00668 }; 00669 void get_file_content(char* file_name, unsigned int* size, unsigned char** content) 00670 { 00671 FILE *fh = fopen(file_name, "rw"); 00672 if ( fh == NULL ) { 00673 perror(file_name); 00674 return; 00675 } 00676 fseek(fh, 0, SEEK_END); 00677 *size = ftell(fh); 00678 rewind(fh); 00679 *content = NULL; 00680 *content = (unsigned char*)malloc(*size); 00681 if ( *size != fread(*content, *size, 1, fh) ) 00682 return; 00683 fclose(fh); 00684 return; 00685 } 00686 00687 int main(int argc, char **argv) 00688 { 00689 //dtls_context_t *dtls_context = NULL; 00690 fd_set rfds; 00691 struct timeval timeout; 00692 int sock, result; 00693 int on = 1; 00694 int res; 00695 00696 dtls_init(); 00697 memset(&session, 0, sizeof(session_t)); 00698 00699 /* resolve destination address where server should be sent */ 00700 res = resolve_address(COAPS_SRV, &session.addr.sa); 00701 00702 if (res < 0) { 00703 PRINTF("failed to resolve address\n"); 00704 exit(-1); 00705 } 00706 session.size = res; 00707 session.addr.sin.sin_port = htons(COAPS_SRV_PORT); 00708 00709 sock = socket(session.addr.sa.sa_family, SOCK_DGRAM, 0); 00710 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 00711 00712 dtls_context = dtls_new_context(&sock); 00713 00714 if (!dtls_context) { 00715 PRINTF("cannot create context\n"); 00716 exit(-1); 00717 } 00718 00719 dtls_set_handler(dtls_context, &cb); 00720 dtls_connect(dtls_context, &session); 00721 00722 while (1) { 00723 FD_ZERO(&rfds); 00724 FD_SET(sock, &rfds); 00725 00726 timeout.tv_sec = 2; 00727 timeout.tv_usec = 0; 00728 00729 result = select(sock+1, &rfds, 0, 0, &timeout); 00730 00731 if (result < 0) { // error 00732 if (errno != EINTR) 00733 perror("select"); 00734 } else if (result == 0) { // timeout 00735 if (last_sent.out > 0 && last_sent.ack == 0) { 00736 if ((int)time(NULL) - last_sent.out > TIMEOUT) { // TIMEOUT 00737 if (last_sent.retry <= MAX_RETRY) { 00738 dtls_write(dtls_context, &session, last_sent.data, sent_pdu->length); 00739 SET_SEND_TIMESTAMP(); 00740 } else { 00741 PRINTF("Failed: reach retry limit"); 00742 break; 00743 } 00744 } 00745 } 00746 } else { // ok 00747 if (FD_ISSET(sock, &rfds)) { 00748 dtls_handle_read(dtls_context); 00749 } 00750 } 00751 if (dtls_connected && !ready_to_recv) { 00752 if (test_cases & TEST_WRITE) { 00753 sent_pdu = get_pdu_write1p(cik ,alias, value_to_write); 00754 PRINTF("Write data '%s' to '%s'..\n", value_to_write, alias); 00755 dtls_write(dtls_context, &session, (uint8*)sent_pdu->hdr, sent_pdu->length); 00756 test_cases -= TEST_WRITE; 00757 ready_to_recv = 1; 00758 continue; 00759 } 00760 if (test_cases & TEST_READ) { 00761 sent_pdu = get_pdu_read1p(cik ,alias); 00762 PRINTF("Read data from alias '%s'..\n", alias); 00763 dtls_write(dtls_context, &session, (uint8*)sent_pdu->hdr, sent_pdu->length); 00764 test_cases -= TEST_READ; 00765 ready_to_recv = 1; 00766 continue; 00767 } 00768 } 00769 if (!test_cases && !ready_to_recv) 00770 break; 00771 } 00772 dtls_free_context(dtls_context); 00773 exit(0); 00774 } 00775 00776 00777 void hex_dump(uint8_t* bytes, size_t len) 00778 { 00779 size_t i, j; 00780 for (i = 0; i < len; i+=16){ 00781 printf(" 0x%.3zx ", i); 00782 for (j = 0; j < 16; j++){ 00783 if (i+j < len) 00784 printf("%02hhx ", bytes[i+j]); 00785 else 00786 printf("%s ", "--"); 00787 } 00788 printf(" %.*s\n", (int)(16 > len-i ? len-i : 16), bytes+i); 00789 } 00790 } 00791 00792 void coap_pretty_print(uint8_t* pkt, size_t len) 00793 { 00794 size_t i; 00795 uint8_t *ptr; 00796 int32_t opt_num, j, k; 00797 00798 if(coap_validate_pkt(pkt, len) == CS_OK){ 00799 printf(" ------ Valid CoAP Packet (%zi) ------ \n", len); 00800 printf("Type: %i\n",coap_get_type(pkt, len)); 00801 printf("Code: %i.%02i\n", coap_get_code_class(pkt, len), coap_get_code_detail(pkt, len)); 00802 j = coap_get_option_count(pkt, len); 00803 for(i = 0; i < j; i++){ 00804 k = coap_get_option(pkt, len, i, &opt_num, &ptr); 00805 00806 printf("Option: %i\n", opt_num); 00807 printf(" Value: %.*s (%i)\n", k, ptr, k); 00808 } 00809 j = coap_get_payload(pkt, len, &ptr); 00810 printf("Value: %.*s (%i)\n", j, ptr, j); 00811 }else{ 00812 printf(" ------ Non-CoAP Message (%zi) ------ \n", len); 00813 hex_dump(pkt, len); 00814 } 00815 }
Generated on Tue Jul 12 2022 18:09:07 by
1.7.2