2 /* This is needed for apple */
3 #define __APPLE_USE_RFC_3542
5 #include "iotivity_config.h"
13 #ifdef HAVE_NETINET_IN_H
14 #include <netinet/in.h>
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_SOCKET_H
18 #include <sys/socket.h>
20 #ifdef HAVE_SYS_TIME_H
28 #include "platform_features.h"
35 #define DTLS_PRIVATE_KEY_SIZE (32)
36 #define DTLS_PUBLIC_KEY_SIZE (64)
39 #define DEFAULT_PORT 20220
44 * General purpose byte array structure.
46 * Contains pointer to array of bytes and it's length.
51 uint8_t *data; /**< Pointer to the byte array */
52 size_t len; /**< Data size */
56 /**@def BYTE_ARRAY_INITIALIZER
58 * Initializes of existing byte array pointer to \a NULL.
60 #undef BYTE_ARRAY_INITIALIZER
61 #define BYTE_ARRAY_INITIALIZER {NULL, 0}
64 #define X509_OPTIONS "x:r:u:"
65 #define SERVER_CRT_LEN 295
66 static const unsigned char g_server_certificate[SERVER_CRT_LEN] = {
68 0x30, 0x82, 0x01, 0x20, 0x30, 0x81, 0xc4, 0xa0,
69 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x37,
70 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
71 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x17,
72 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
73 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
74 0x20, 0x49, 0x53, 0x53, 0x55, 0x45, 0x52, 0x30,
75 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31, 0x30,
76 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
77 0x17, 0x0d, 0x34, 0x39, 0x30, 0x31, 0x30, 0x31,
78 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
79 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
80 0x04, 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61,
81 0x6c, 0x20, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52,
82 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
83 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
84 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
85 0x42, 0x00, 0x04, 0x07, 0x88, 0x10, 0xdc, 0x62,
86 0xd7, 0xe6, 0x9b, 0x7c, 0xad, 0x6e, 0x78, 0xb0,
87 0x5f, 0x9a, 0x00, 0x11, 0x74, 0x2c, 0x8b, 0xaf,
88 0x09, 0x65, 0x7c, 0x86, 0x8e, 0x55, 0xcb, 0x39,
89 0x55, 0x72, 0xc6, 0x65, 0x71, 0xcd, 0x03, 0xdc,
90 0x2a, 0x4f, 0x46, 0x5b, 0x14, 0xc8, 0x27, 0x74,
91 0xab, 0xf4, 0x1f, 0xc1, 0x35, 0x0d, 0x42, 0xbc,
92 0xc2, 0x9f, 0xb5, 0xc1, 0x79, 0xb6, 0x8b, 0xca,
93 0xdb, 0xff, 0x82, 0x30, 0x0c, 0x06, 0x08, 0x2a,
94 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05,
95 0x00, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21,
96 0x00, 0xb1, 0x81, 0x81, 0x92, 0x0e, 0x76, 0x7c,
97 0xeb, 0xf5, 0x37, 0xde, 0x27, 0xc4, 0x01, 0xc8,
98 0x96, 0xc3, 0xe5, 0x9f, 0x47, 0x7e, 0x25, 0x92,
99 0xa4, 0xba, 0x22, 0x25, 0xa3, 0x81, 0x19, 0xcf,
100 0x0d, 0x02, 0x21, 0x00, 0xca, 0x92, 0xbe, 0x79,
101 0xc7, 0x82, 0x84, 0x64, 0xc4, 0xc4, 0xf4, 0x3d,
102 0x69, 0x79, 0x68, 0xc0, 0xf1, 0xba, 0xaf, 0x6c,
103 0xbb, 0xdd, 0x54, 0x7d, 0x07, 0xe7, 0x53, 0x3b,
104 0xc3, 0x1b, 0x87, 0x04};
106 //default server's key pair
107 static const unsigned char x509_priv_key[] = {
108 0xaa, 0xa3, 0x46, 0xf1, 0x3c, 0x56, 0x5d, 0x08,
109 0x5e, 0x59, 0xba, 0x7f, 0xd2, 0x21, 0x62, 0xc6,
110 0xcc, 0x5d, 0xfa, 0x3f, 0xb5, 0x25, 0xa9, 0x89,
111 0x4f, 0x32, 0xe8, 0x2a, 0xe0, 0xee, 0x9b, 0x4c};
113 static const unsigned char x509_pub_key_x[] = {
114 0x07, 0x88, 0x10, 0xdc, 0x62, 0xd7, 0xe6, 0x9b,
115 0x7c, 0xad, 0x6e, 0x78, 0xb0, 0x5f, 0x9a, 0x00,
116 0x11, 0x74, 0x2c, 0x8b, 0xaf, 0x09, 0x65, 0x7c,
117 0x86, 0x8e, 0x55, 0xcb, 0x39, 0x55, 0x72, 0xc6};
119 static const unsigned char x509_pub_key_y[] = {
120 0x65, 0x71, 0xcd, 0x03, 0xdc, 0x2a, 0x4f, 0x46,
121 0x5b, 0x14, 0xc8, 0x27, 0x74, 0xab, 0xf4, 0x1f,
122 0xc1, 0x35, 0x0d, 0x42, 0xbc, 0xc2, 0x9f, 0xb5,
123 0xc1, 0x79, 0xb6, 0x8b, 0xca, 0xdb, 0xff, 0x82};
126 static const unsigned char x509_ca_pub_x[] = {
127 0x57, 0x94, 0x7f, 0x98, 0x7a, 0x02, 0x67, 0x09,
128 0x25, 0xc1, 0xcb, 0x5a, 0xf5, 0x46, 0xfb, 0xad,
129 0xf7, 0x68, 0x94, 0x8c, 0xa7, 0xe3, 0xf0, 0x5b,
130 0xc3, 0x6b, 0x5c, 0x9b, 0xd3, 0x7d, 0x74, 0x12
133 static const unsigned char x509_ca_pub_y[] = {
134 0xce, 0x68, 0xbc, 0x55, 0xf5, 0xf8, 0x1b, 0x3d,
135 0xef, 0xed, 0x1f, 0x2b, 0xd2, 0x69, 0x5d, 0xcf,
136 0x79, 0x16, 0xa6, 0xbd, 0x97, 0x96, 0x27, 0x60,
137 0x5d, 0xd1, 0xb7, 0x93, 0xa2, 0x4a, 0x62, 0x4d
140 static const unsigned char client_pub_key_x[] = {
141 0xe3, 0xd1, 0x67, 0x1e, 0xdc, 0x46, 0xf4, 0x19,
142 0x50, 0x15, 0x2e, 0x3a, 0x2f, 0xd8, 0x68, 0x6b,
143 0x37, 0x32, 0x84, 0x9e, 0x83, 0x81, 0xbf, 0x25,
144 0x5d, 0xbb, 0x18, 0x07, 0x3c, 0xbd, 0xf3, 0xab};
146 static const unsigned char client_pub_key_y[] = {
147 0xd3, 0xbf, 0x53, 0x59, 0xc9, 0x1e, 0xce, 0x5b,
148 0x39, 0x6a, 0xe5, 0x60, 0xf3, 0x70, 0xdb, 0x66,
149 0xb6, 0x80, 0xcb, 0x65, 0x0b, 0x35, 0x2a, 0x62,
150 0x44, 0x89, 0x63, 0x64, 0x6f, 0x6f, 0xbd, 0xf0};
152 static unsigned char x509_server_cert[DTLS_MAX_CERT_SIZE];
153 static size_t x509_server_cert_len = 0;
154 static unsigned char x509_server_priv[DTLS_PRIVATE_KEY_SIZE+1];
155 static size_t x509_server_priv_is_set = 0;
156 static unsigned char x509_ca_pub[DTLS_PUBLIC_KEY_SIZE+1];
157 static size_t x509_ca_pub_is_set = 0;
159 static int x509_info_from_file = 0;
162 static const unsigned char ecdsa_priv_key[] = {
163 0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05,
164 0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF,
165 0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70,
166 0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4};
168 static const unsigned char ecdsa_pub_key_x[] = {
169 0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06,
170 0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A,
171 0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2,
172 0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A};
174 static const unsigned char ecdsa_pub_key_y[] = {
175 0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA,
176 0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31,
177 0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D,
178 0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70};
181 /* SIGINT handler: set quit to 1 for graceful termination */
183 handle_sigint(int signum) {
184 dsrv_stop(dsrv_get_context());
190 read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) {
200 bytes_read = fread(buf, 1, max_buf_len, f);
207 result += bytes_read;
208 max_buf_len -= bytes_read;
218 #define PSK_SERVER_HINT "Server_identity"
220 /* This function is the "key store" for tinyDTLS. It is called to
221 * retrieve a key for the given identity within this particular
224 get_psk_info(struct dtls_context_t *ctx, const session_t *session,
225 dtls_credentials_type_t type,
226 const unsigned char *id, size_t id_len,
227 unsigned char *result, size_t result_length) {
237 { (unsigned char *)"Client_identity", 15,
238 (unsigned char *)"secretPSK", 9 },
239 { (unsigned char *)"default identity", 16,
240 (unsigned char *)"\x11\x22\x33", 3 },
241 { (unsigned char *)"\0", 2,
242 (unsigned char *)"", 1 }
247 if (result_length < strlen(PSK_SERVER_HINT)) {
248 dtls_warn("cannot set psk_hint -- buffer too small\n");
249 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
252 memcpy(result, PSK_SERVER_HINT, strlen(PSK_SERVER_HINT));
253 return strlen(PSK_SERVER_HINT);
258 for (i = 0; i < (int)(sizeof(psk)/sizeof(struct keymap_t)); i++) {
259 if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
260 if (result_length < psk[i].key_length) {
261 dtls_warn("buffer too small for PSK");
262 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
265 memcpy(result, psk[i].key, psk[i].key_length);
266 return psk[i].key_length;
273 dtls_warn("unsupported request type: %d\n", type);
276 return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
279 #endif /* DTLS_PSK */
283 get_ecdsa_key(struct dtls_context_t *ctx,
284 const session_t *session,
285 const dtls_ecc_key_t **result) {
288 static const dtls_ecc_key_t ecdsa_key = {
289 .curve = DTLS_ECDH_CURVE_SECP256R1,
290 .priv_key = ecdsa_priv_key,
291 .pub_key_x = ecdsa_pub_key_x,
292 .pub_key_y = ecdsa_pub_key_y
295 *result = &ecdsa_key;
300 verify_ecdsa_key(struct dtls_context_t *ctx,
301 const session_t *session,
302 const unsigned char *other_pub_x,
303 const unsigned char *other_pub_y,
312 #endif /* DTLS_ECC */
316 get_x509_key(struct dtls_context_t *ctx,
317 const session_t *session,
318 const dtls_ecc_key_t **result) {
321 static dtls_ecc_key_t ecdsa_key = {
322 .curve = DTLS_ECDH_CURVE_SECP256R1,
323 .priv_key = x509_priv_key,
324 .pub_key_x = x509_pub_key_x,
325 .pub_key_y = x509_pub_key_y
327 if (x509_info_from_file)
328 ecdsa_key.priv_key = x509_server_priv;
330 *result = &ecdsa_key;
335 get_x509_cert(struct dtls_context_t *ctx,
336 const session_t *session,
337 const unsigned char **cert,
342 if (x509_info_from_file)
344 *cert = x509_server_cert;
345 *cert_size = x509_server_cert_len;
349 *cert = g_server_certificate;
350 *cert_size = SERVER_CRT_LEN;
356 static int check_certificate(byte_array cert_der_code, byte_array ca_public_key)
363 static int verify_x509_cert(struct dtls_context_t *ctx, const session_t *session,
364 const unsigned char *cert, size_t cert_size,
371 const unsigned char *ca_pub_x;
372 const unsigned char *ca_pub_y;
373 byte_array cert_der_code = BYTE_ARRAY_INITIALIZER;
374 byte_array ca_public_key = BYTE_ARRAY_INITIALIZER;
375 unsigned char ca_pub_key[DTLS_PUBLIC_KEY_SIZE];
379 if (x509_info_from_file)
381 ca_pub_x = x509_ca_pub;
382 ca_pub_y = x509_ca_pub + DTLS_PUBLIC_KEY_SIZE/2;
386 ca_pub_x = x509_ca_pub_x;
387 ca_pub_y = x509_ca_pub_y;
390 cert_der_code.data = (uint8_t *)cert;
391 cert_der_code.len = cert_size;
393 ca_public_key.len = DTLS_PUBLIC_KEY_SIZE;
394 ca_public_key.data = ca_pub_key;
395 memcpy(ca_public_key.data, ca_pub_x, DTLS_PUBLIC_KEY_SIZE/2);
396 memcpy(ca_public_key.data + DTLS_PUBLIC_KEY_SIZE/2, ca_pub_y, DTLS_PUBLIC_KEY_SIZE/2);
398 memcpy(x, client_pub_key_x, x_size);
399 memcpy(y, client_pub_key_y, y_size);
401 ret = (int) check_certificate(cert_der_code, ca_public_key);
406 static int is_x509_active(struct dtls_context_t *ctx)
411 #endif /* DTLS_X509 */
414 #define DTLS_SERVER_CMD_CLOSE "server:close"
415 #define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate"
418 read_from_peer(struct dtls_context_t *ctx,
419 session_t *session, uint8 *data, size_t len) {
421 for (i = 0; i < len; i++)
422 printf("%c", data[i]);
423 if (len >= strlen(DTLS_SERVER_CMD_CLOSE) &&
424 !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) {
425 printf("server: closing connection\n");
426 dtls_close(ctx, session);
428 } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) &&
429 !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) {
430 printf("server: renegotiate connection\n");
431 dtls_renegotiate(ctx, session);
435 return dtls_write(ctx, session, data, len);
439 send_to_peer(struct dtls_context_t *ctx,
440 session_t *session, uint8 *data, size_t len) {
442 int fd = *(int *)dtls_get_app_data(ctx);
443 return sendto(fd, data, len, MSG_DONTWAIT,
444 &session->addr.sa, session->size);
448 dtls_handle_read(struct dtls_context_t *ctx) {
451 static uint8 buf[DTLS_MAX_BUF];
454 fd = dtls_get_app_data(ctx);
458 memset(&session, 0, sizeof(session_t));
459 session.size = sizeof(session.addr);
460 len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC,
461 &session.addr.sa, &session.size);
467 dtls_debug("got %d bytes from port %d\n", len,
468 ntohs(session.addr.sin6.sin6_port));
469 if ((int)(sizeof(buf)) < len) {
470 dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf));
474 return dtls_handle_message(ctx, &session, buf, len);
478 resolve_address(const char *server, struct sockaddr *dst) {
480 struct addrinfo *res, *ainfo;
481 struct addrinfo hints;
482 static char addrstr[256];
485 memset(addrstr, 0, sizeof(addrstr));
486 if (server && strlen(server) > 0)
487 memcpy(addrstr, server, strlen(server));
489 memcpy(addrstr, "localhost", 9);
491 memset ((char *)&hints, 0, sizeof(hints));
492 hints.ai_socktype = SOCK_DGRAM;
493 hints.ai_family = AF_UNSPEC;
495 error = getaddrinfo(addrstr, "", &hints, &res);
498 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
502 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
504 switch (ainfo->ai_family) {
507 memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
508 return ainfo->ai_addrlen;
519 usage(const char *program, const char *version) {
522 p = strrchr( program, '/' );
526 fprintf(stderr, "%s v%s -- DTLS server implementation\n"
527 "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
528 "usage: %s [-A address] [-p port] [-v num] [-a enable|disable]\n"
530 " [-x file] [-r file] [-u file]"
531 #endif /* DTLS_X509 */
532 "\t-A address\t\tlisten on specified address (default is ::)\n"
533 "\t-p port\t\tlisten on specified port (default is %d)\n"
534 "\t-v num\t\tverbosity level (default: 3)\n"
535 "\t-a enable|disable\t(default: disable)\n"
536 "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
537 "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
539 "\t-x file\tread Server certificate from file\n"
540 "\t-r file\tread Server private key from file\n"
541 "\t-u file\tread CA public key from file\n"
542 #endif /* DTLS_X509 */
543 ,program, version, program, DEFAULT_PORT);
546 static dtls_handler_t cb = {
547 .write = send_to_peer,
548 .read = read_from_peer,
551 .get_psk_info = get_psk_info,
552 #endif /* DTLS_PSK */
554 .get_ecdsa_key = get_ecdsa_key,
555 .verify_ecdsa_key = verify_ecdsa_key,
556 #endif /* DTLS_ECC */
558 .get_x509_key = get_x509_key,
559 .verify_x509_cert = verify_x509_cert,
560 .get_x509_cert = get_x509_cert,
561 .is_x509_active = is_x509_active,
567 main(int argc, char **argv) {
568 dtls_context_t *the_context = NULL;
569 log_t log_level = DTLS_LOG_WARN;
571 struct timeval timeout;
574 dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
575 struct sockaddr_in6 listen_addr;
577 memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
579 /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */
580 #if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN)
581 listen_addr.sin6_len = sizeof(struct sockaddr_in6);
584 listen_addr.sin6_family = AF_INET6;
585 listen_addr.sin6_port = htons(DEFAULT_PORT);
586 listen_addr.sin6_addr = in6addr_any;
588 while ((opt = getopt(argc, argv, "A:p:v:a:")) != -1) {
591 if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
592 fprintf(stderr, "cannot resolve address\n");
597 listen_addr.sin6_port = htons(atoi(optarg));
600 log_level = strtol(optarg, NULL, 10);
603 if( strcmp(optarg, "enable") == 0)
604 ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
609 ssize_t result = read_from_file(optarg, x509_server_cert, DTLS_MAX_CERT_SIZE);
612 dtls_warn("Cannot read Server certificate. Using default\n");
616 x509_server_cert_len = result;
622 ssize_t result = read_from_file(optarg, x509_server_priv, DTLS_PRIVATE_KEY_SIZE+1);
625 dtls_warn("Cannot read Server private key. Using default\n");
629 x509_server_priv_is_set = result;
635 ssize_t result = read_from_file(optarg, x509_ca_pub, DTLS_PUBLIC_KEY_SIZE+1);
638 dtls_warn("Cannot read CA public key. Using default\n");
642 x509_ca_pub_is_set = result;
646 #endif /* DTLS_X509 */
648 usage(argv[0], dtls_package_version());
653 dtls_set_log_level(log_level);
656 if (x509_server_cert_len && x509_server_priv_is_set && x509_ca_pub_is_set)
658 x509_info_from_file = 1;
660 else if(!(x509_server_cert_len || x509_server_priv_is_set || x509_ca_pub_is_set))
662 x509_info_from_file = 0;
666 fprintf(stderr,"please set -x, -r, -u options simultaneously");
667 usage(argv[0], dtls_package_version());
670 #endif /* DTLS_X509 */
672 /* init socket and set it to non-blocking */
673 fd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0);
676 dtls_alert("socket: %s\n", strerror(errno));
680 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on) ) < 0) {
681 dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
684 flags = fcntl(fd, F_GETFL, 0);
685 if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
686 dtls_alert("fcntl: %s\n", strerror(errno));
691 #ifdef IPV6_RECVPKTINFO
692 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
693 #else /* IPV6_RECVPKTINFO */
694 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
695 #endif /* IPV6_RECVPKTINFO */
696 dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
699 if (bind(fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
700 dtls_alert("bind: %s\n", strerror(errno));
706 the_context = dtls_new_context(&fd);
708 /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
709 dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
711 dtls_set_handler(the_context, &cb);
718 /* FD_SET(fd, &wfds); */
723 result = select( fd+1, &rfds, &wfds, 0, &timeout);
725 if (result < 0) { /* error */
728 } else if (result == 0) { /* timeout */
730 if (FD_ISSET(fd, &wfds))
732 else if (FD_ISSET(fd, &rfds)) {
733 dtls_handle_read(the_context);
739 dtls_free_context(the_context);