2 /* This is needed for apple */
3 #define __APPLE_USE_RFC_3542
12 #ifdef HAVE_NETINET_IN_H
13 #include <netinet/in.h>
15 #include <sys/types.h>
16 #ifdef HAVE_SYS_SOCKET_H
17 #include <sys/socket.h>
19 #ifdef HAVE_SYS_TIME_H
27 #include "platform_features.h"
34 #define DTLS_PRIVATE_KEY_SIZE (32)
35 #define DTLS_PUBLIC_KEY_SIZE (64)
38 #define DEFAULT_PORT 20220
43 * General purpose byte array structure.
45 * Contains pointer to array of bytes and it's length.
50 uint8_t *data; /**< Pointer to the byte array */
51 size_t len; /**< Data size */
55 /**@def BYTE_ARRAY_INITIALIZER
57 * Initializes of existing byte array pointer to \a NULL.
59 #undef BYTE_ARRAY_INITIALIZER
60 #define BYTE_ARRAY_INITIALIZER {NULL, 0}
63 #define X509_OPTIONS "x:r:u:"
64 #define SERVER_CRT_LEN 295
65 static const unsigned char g_server_certificate[SERVER_CRT_LEN] = {
67 0x30, 0x82, 0x01, 0x20, 0x30, 0x81, 0xc4, 0xa0,
68 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x37,
69 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
70 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x17,
71 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
72 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
73 0x20, 0x49, 0x53, 0x53, 0x55, 0x45, 0x52, 0x30,
74 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31, 0x30,
75 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
76 0x17, 0x0d, 0x34, 0x39, 0x30, 0x31, 0x30, 0x31,
77 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
78 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
79 0x04, 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61,
80 0x6c, 0x20, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52,
81 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
82 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
83 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
84 0x42, 0x00, 0x04, 0x07, 0x88, 0x10, 0xdc, 0x62,
85 0xd7, 0xe6, 0x9b, 0x7c, 0xad, 0x6e, 0x78, 0xb0,
86 0x5f, 0x9a, 0x00, 0x11, 0x74, 0x2c, 0x8b, 0xaf,
87 0x09, 0x65, 0x7c, 0x86, 0x8e, 0x55, 0xcb, 0x39,
88 0x55, 0x72, 0xc6, 0x65, 0x71, 0xcd, 0x03, 0xdc,
89 0x2a, 0x4f, 0x46, 0x5b, 0x14, 0xc8, 0x27, 0x74,
90 0xab, 0xf4, 0x1f, 0xc1, 0x35, 0x0d, 0x42, 0xbc,
91 0xc2, 0x9f, 0xb5, 0xc1, 0x79, 0xb6, 0x8b, 0xca,
92 0xdb, 0xff, 0x82, 0x30, 0x0c, 0x06, 0x08, 0x2a,
93 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05,
94 0x00, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21,
95 0x00, 0xb1, 0x81, 0x81, 0x92, 0x0e, 0x76, 0x7c,
96 0xeb, 0xf5, 0x37, 0xde, 0x27, 0xc4, 0x01, 0xc8,
97 0x96, 0xc3, 0xe5, 0x9f, 0x47, 0x7e, 0x25, 0x92,
98 0xa4, 0xba, 0x22, 0x25, 0xa3, 0x81, 0x19, 0xcf,
99 0x0d, 0x02, 0x21, 0x00, 0xca, 0x92, 0xbe, 0x79,
100 0xc7, 0x82, 0x84, 0x64, 0xc4, 0xc4, 0xf4, 0x3d,
101 0x69, 0x79, 0x68, 0xc0, 0xf1, 0xba, 0xaf, 0x6c,
102 0xbb, 0xdd, 0x54, 0x7d, 0x07, 0xe7, 0x53, 0x3b,
103 0xc3, 0x1b, 0x87, 0x04};
105 //default server's key pair
106 static const unsigned char x509_priv_key[] = {
107 0xaa, 0xa3, 0x46, 0xf1, 0x3c, 0x56, 0x5d, 0x08,
108 0x5e, 0x59, 0xba, 0x7f, 0xd2, 0x21, 0x62, 0xc6,
109 0xcc, 0x5d, 0xfa, 0x3f, 0xb5, 0x25, 0xa9, 0x89,
110 0x4f, 0x32, 0xe8, 0x2a, 0xe0, 0xee, 0x9b, 0x4c};
112 static const unsigned char x509_pub_key_x[] = {
113 0x07, 0x88, 0x10, 0xdc, 0x62, 0xd7, 0xe6, 0x9b,
114 0x7c, 0xad, 0x6e, 0x78, 0xb0, 0x5f, 0x9a, 0x00,
115 0x11, 0x74, 0x2c, 0x8b, 0xaf, 0x09, 0x65, 0x7c,
116 0x86, 0x8e, 0x55, 0xcb, 0x39, 0x55, 0x72, 0xc6};
118 static const unsigned char x509_pub_key_y[] = {
119 0x65, 0x71, 0xcd, 0x03, 0xdc, 0x2a, 0x4f, 0x46,
120 0x5b, 0x14, 0xc8, 0x27, 0x74, 0xab, 0xf4, 0x1f,
121 0xc1, 0x35, 0x0d, 0x42, 0xbc, 0xc2, 0x9f, 0xb5,
122 0xc1, 0x79, 0xb6, 0x8b, 0xca, 0xdb, 0xff, 0x82};
125 static const unsigned char x509_ca_pub_x[] = {
126 0x57, 0x94, 0x7f, 0x98, 0x7a, 0x02, 0x67, 0x09,
127 0x25, 0xc1, 0xcb, 0x5a, 0xf5, 0x46, 0xfb, 0xad,
128 0xf7, 0x68, 0x94, 0x8c, 0xa7, 0xe3, 0xf0, 0x5b,
129 0xc3, 0x6b, 0x5c, 0x9b, 0xd3, 0x7d, 0x74, 0x12
132 static const unsigned char x509_ca_pub_y[] = {
133 0xce, 0x68, 0xbc, 0x55, 0xf5, 0xf8, 0x1b, 0x3d,
134 0xef, 0xed, 0x1f, 0x2b, 0xd2, 0x69, 0x5d, 0xcf,
135 0x79, 0x16, 0xa6, 0xbd, 0x97, 0x96, 0x27, 0x60,
136 0x5d, 0xd1, 0xb7, 0x93, 0xa2, 0x4a, 0x62, 0x4d
139 static const unsigned char client_pub_key_x[] = {
140 0xe3, 0xd1, 0x67, 0x1e, 0xdc, 0x46, 0xf4, 0x19,
141 0x50, 0x15, 0x2e, 0x3a, 0x2f, 0xd8, 0x68, 0x6b,
142 0x37, 0x32, 0x84, 0x9e, 0x83, 0x81, 0xbf, 0x25,
143 0x5d, 0xbb, 0x18, 0x07, 0x3c, 0xbd, 0xf3, 0xab};
145 static const unsigned char client_pub_key_y[] = {
146 0xd3, 0xbf, 0x53, 0x59, 0xc9, 0x1e, 0xce, 0x5b,
147 0x39, 0x6a, 0xe5, 0x60, 0xf3, 0x70, 0xdb, 0x66,
148 0xb6, 0x80, 0xcb, 0x65, 0x0b, 0x35, 0x2a, 0x62,
149 0x44, 0x89, 0x63, 0x64, 0x6f, 0x6f, 0xbd, 0xf0};
151 static unsigned char x509_server_cert[DTLS_MAX_CERT_SIZE];
152 static size_t x509_server_cert_len = 0;
153 static unsigned char x509_server_priv[DTLS_PRIVATE_KEY_SIZE+1];
154 static size_t x509_server_priv_is_set = 0;
155 static unsigned char x509_ca_pub[DTLS_PUBLIC_KEY_SIZE+1];
156 static size_t x509_ca_pub_is_set = 0;
158 static int x509_info_from_file = 0;
161 static const unsigned char ecdsa_priv_key[] = {
162 0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05,
163 0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF,
164 0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70,
165 0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4};
167 static const unsigned char ecdsa_pub_key_x[] = {
168 0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06,
169 0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A,
170 0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2,
171 0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A};
173 static const unsigned char ecdsa_pub_key_y[] = {
174 0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA,
175 0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31,
176 0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D,
177 0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70};
180 /* SIGINT handler: set quit to 1 for graceful termination */
182 handle_sigint(int signum) {
183 dsrv_stop(dsrv_get_context());
189 read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) {
199 bytes_read = fread(buf, 1, max_buf_len, f);
206 result += bytes_read;
207 max_buf_len -= bytes_read;
217 #define PSK_SERVER_HINT "Server_identity"
219 /* This function is the "key store" for tinyDTLS. It is called to
220 * retrieve a key for the given identity within this particular
223 get_psk_info(struct dtls_context_t *ctx, const session_t *session,
224 dtls_credentials_type_t type,
225 const unsigned char *id, size_t id_len,
226 unsigned char *result, size_t result_length) {
236 { (unsigned char *)"Client_identity", 15,
237 (unsigned char *)"secretPSK", 9 },
238 { (unsigned char *)"default identity", 16,
239 (unsigned char *)"\x11\x22\x33", 3 },
240 { (unsigned char *)"\0", 2,
241 (unsigned char *)"", 1 }
246 if (result_length < strlen(PSK_SERVER_HINT)) {
247 dtls_warn("cannot set psk_hint -- buffer too small\n");
248 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
251 memcpy(result, PSK_SERVER_HINT, strlen(PSK_SERVER_HINT));
252 return strlen(PSK_SERVER_HINT);
257 for (i = 0; i < (int)(sizeof(psk)/sizeof(struct keymap_t)); i++) {
258 if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
259 if (result_length < psk[i].key_length) {
260 dtls_warn("buffer too small for PSK");
261 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
264 memcpy(result, psk[i].key, psk[i].key_length);
265 return psk[i].key_length;
272 dtls_warn("unsupported request type: %d\n", type);
275 return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
278 #endif /* DTLS_PSK */
282 get_ecdsa_key(struct dtls_context_t *ctx,
283 const session_t *session,
284 const dtls_ecc_key_t **result) {
287 static const dtls_ecc_key_t ecdsa_key = {
288 .curve = DTLS_ECDH_CURVE_SECP256R1,
289 .priv_key = ecdsa_priv_key,
290 .pub_key_x = ecdsa_pub_key_x,
291 .pub_key_y = ecdsa_pub_key_y
294 *result = &ecdsa_key;
299 verify_ecdsa_key(struct dtls_context_t *ctx,
300 const session_t *session,
301 const unsigned char *other_pub_x,
302 const unsigned char *other_pub_y,
311 #endif /* DTLS_ECC */
315 get_x509_key(struct dtls_context_t *ctx,
316 const session_t *session,
317 const dtls_ecc_key_t **result) {
320 static dtls_ecc_key_t ecdsa_key = {
321 .curve = DTLS_ECDH_CURVE_SECP256R1,
322 .priv_key = x509_priv_key,
323 .pub_key_x = x509_pub_key_x,
324 .pub_key_y = x509_pub_key_y
326 if (x509_info_from_file)
327 ecdsa_key.priv_key = x509_server_priv;
329 *result = &ecdsa_key;
334 get_x509_cert(struct dtls_context_t *ctx,
335 const session_t *session,
336 const unsigned char **cert,
341 if (x509_info_from_file)
343 *cert = x509_server_cert;
344 *cert_size = x509_server_cert_len;
348 *cert = g_server_certificate;
349 *cert_size = SERVER_CRT_LEN;
355 static int check_certificate(byte_array cert_der_code, byte_array ca_public_key)
362 static int verify_x509_cert(struct dtls_context_t *ctx, const session_t *session,
363 const unsigned char *cert, size_t cert_size,
370 const unsigned char *ca_pub_x;
371 const unsigned char *ca_pub_y;
372 byte_array cert_der_code = BYTE_ARRAY_INITIALIZER;
373 byte_array ca_public_key = BYTE_ARRAY_INITIALIZER;
374 unsigned char ca_pub_key[DTLS_PUBLIC_KEY_SIZE];
378 if (x509_info_from_file)
380 ca_pub_x = x509_ca_pub;
381 ca_pub_y = x509_ca_pub + DTLS_PUBLIC_KEY_SIZE/2;
385 ca_pub_x = x509_ca_pub_x;
386 ca_pub_y = x509_ca_pub_y;
389 cert_der_code.data = (uint8_t *)cert;
390 cert_der_code.len = cert_size;
392 ca_public_key.len = DTLS_PUBLIC_KEY_SIZE;
393 ca_public_key.data = ca_pub_key;
394 memcpy(ca_public_key.data, ca_pub_x, DTLS_PUBLIC_KEY_SIZE/2);
395 memcpy(ca_public_key.data + DTLS_PUBLIC_KEY_SIZE/2, ca_pub_y, DTLS_PUBLIC_KEY_SIZE/2);
397 memcpy(x, client_pub_key_x, x_size);
398 memcpy(y, client_pub_key_y, y_size);
400 ret = (int) check_certificate(cert_der_code, ca_public_key);
405 static int is_x509_active(struct dtls_context_t *ctx)
410 #endif /* DTLS_X509 */
413 #define DTLS_SERVER_CMD_CLOSE "server:close"
414 #define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate"
417 read_from_peer(struct dtls_context_t *ctx,
418 session_t *session, uint8 *data, size_t len) {
420 for (i = 0; i < len; i++)
421 printf("%c", data[i]);
422 if (len >= strlen(DTLS_SERVER_CMD_CLOSE) &&
423 !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) {
424 printf("server: closing connection\n");
425 dtls_close(ctx, session);
427 } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) &&
428 !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) {
429 printf("server: renegotiate connection\n");
430 dtls_renegotiate(ctx, session);
434 return dtls_write(ctx, session, data, len);
438 send_to_peer(struct dtls_context_t *ctx,
439 session_t *session, uint8 *data, size_t len) {
441 int fd = *(int *)dtls_get_app_data(ctx);
442 return sendto(fd, data, len, MSG_DONTWAIT,
443 &session->addr.sa, session->size);
447 dtls_handle_read(struct dtls_context_t *ctx) {
450 static uint8 buf[DTLS_MAX_BUF];
453 fd = dtls_get_app_data(ctx);
457 memset(&session, 0, sizeof(session_t));
458 session.size = sizeof(session.addr);
459 len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC,
460 &session.addr.sa, &session.size);
466 dtls_debug("got %d bytes from port %d\n", len,
467 ntohs(session.addr.sin6.sin6_port));
468 if ((int)(sizeof(buf)) < len) {
469 dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf));
473 return dtls_handle_message(ctx, &session, buf, len);
477 resolve_address(const char *server, struct sockaddr *dst) {
479 struct addrinfo *res, *ainfo;
480 struct addrinfo hints;
481 static char addrstr[256];
484 memset(addrstr, 0, sizeof(addrstr));
485 if (server && strlen(server) > 0)
486 memcpy(addrstr, server, strlen(server));
488 memcpy(addrstr, "localhost", 9);
490 memset ((char *)&hints, 0, sizeof(hints));
491 hints.ai_socktype = SOCK_DGRAM;
492 hints.ai_family = AF_UNSPEC;
494 error = getaddrinfo(addrstr, "", &hints, &res);
497 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
501 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
503 switch (ainfo->ai_family) {
506 memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
507 return ainfo->ai_addrlen;
518 usage(const char *program, const char *version) {
521 p = strrchr( program, '/' );
525 fprintf(stderr, "%s v%s -- DTLS server implementation\n"
526 "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
527 "usage: %s [-A address] [-p port] [-v num] [-a enable|disable]\n"
529 " [-x file] [-r file] [-u file]"
530 #endif /* DTLS_X509 */
531 "\t-A address\t\tlisten on specified address (default is ::)\n"
532 "\t-p port\t\tlisten on specified port (default is %d)\n"
533 "\t-v num\t\tverbosity level (default: 3)\n"
534 "\t-a enable|disable\t(default: disable)\n"
535 "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
536 "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
538 "\t-x file\tread Server certificate from file\n"
539 "\t-r file\tread Server private key from file\n"
540 "\t-u file\tread CA public key from file\n"
541 #endif /* DTLS_X509 */
542 ,program, version, program, DEFAULT_PORT);
545 static dtls_handler_t cb = {
546 .write = send_to_peer,
547 .read = read_from_peer,
550 .get_psk_info = get_psk_info,
551 #endif /* DTLS_PSK */
553 .get_ecdsa_key = get_ecdsa_key,
554 .verify_ecdsa_key = verify_ecdsa_key,
555 #endif /* DTLS_ECC */
557 .get_x509_key = get_x509_key,
558 .verify_x509_cert = verify_x509_cert,
559 .get_x509_cert = get_x509_cert,
560 .is_x509_active = is_x509_active,
566 main(int argc, char **argv) {
567 dtls_context_t *the_context = NULL;
568 log_t log_level = DTLS_LOG_WARN;
570 struct timeval timeout;
573 dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
574 struct sockaddr_in6 listen_addr;
576 memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
578 /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */
579 #if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN)
580 listen_addr.sin6_len = sizeof(struct sockaddr_in6);
583 listen_addr.sin6_family = AF_INET6;
584 listen_addr.sin6_port = htons(DEFAULT_PORT);
585 listen_addr.sin6_addr = in6addr_any;
587 while ((opt = getopt(argc, argv, "A:p:v:a:")) != -1) {
590 if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
591 fprintf(stderr, "cannot resolve address\n");
596 listen_addr.sin6_port = htons(atoi(optarg));
599 log_level = strtol(optarg, NULL, 10);
602 if( strcmp(optarg, "enable") == 0)
603 ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
608 ssize_t result = read_from_file(optarg, x509_server_cert, DTLS_MAX_CERT_SIZE);
611 dtls_warn("Cannot read Server certificate. Using default\n");
615 x509_server_cert_len = result;
621 ssize_t result = read_from_file(optarg, x509_server_priv, DTLS_PRIVATE_KEY_SIZE+1);
624 dtls_warn("Cannot read Server private key. Using default\n");
628 x509_server_priv_is_set = result;
634 ssize_t result = read_from_file(optarg, x509_ca_pub, DTLS_PUBLIC_KEY_SIZE+1);
637 dtls_warn("Cannot read CA public key. Using default\n");
641 x509_ca_pub_is_set = result;
645 #endif /* DTLS_X509 */
647 usage(argv[0], dtls_package_version());
652 dtls_set_log_level(log_level);
655 if (x509_server_cert_len && x509_server_priv_is_set && x509_ca_pub_is_set)
657 x509_info_from_file = 1;
659 else if(!(x509_server_cert_len || x509_server_priv_is_set || x509_ca_pub_is_set))
661 x509_info_from_file = 0;
665 fprintf(stderr,"please set -x, -r, -u options simultaneously");
666 usage(argv[0], dtls_package_version());
669 #endif /* DTLS_X509 */
671 /* init socket and set it to non-blocking */
672 fd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0);
675 dtls_alert("socket: %s\n", strerror(errno));
679 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on) ) < 0) {
680 dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
683 flags = fcntl(fd, F_GETFL, 0);
684 if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
685 dtls_alert("fcntl: %s\n", strerror(errno));
690 #ifdef IPV6_RECVPKTINFO
691 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
692 #else /* IPV6_RECVPKTINFO */
693 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
694 #endif /* IPV6_RECVPKTINFO */
695 dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
698 if (bind(fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
699 dtls_alert("bind: %s\n", strerror(errno));
705 the_context = dtls_new_context(&fd);
707 /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
708 dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
710 dtls_set_handler(the_context, &cb);
717 /* FD_SET(fd, &wfds); */
722 result = select( fd+1, &rfds, &wfds, 0, &timeout);
724 if (result < 0) { /* error */
727 } else if (result == 0) { /* timeout */
729 if (FD_ISSET(fd, &wfds))
731 else if (FD_ISSET(fd, &rfds)) {
732 dtls_handle_read(the_context);
738 dtls_free_context(the_context);