Skip to content

Commit cb2bbb3

Browse files
committed
Working version with BIO_s_dgram_mem
1 parent f2568d1 commit cb2bbb3

File tree

4 files changed

+183
-86
lines changed

4 files changed

+183
-86
lines changed

c_src/ex_dtls/dtls.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,46 @@ SSL *create_ssl(SSL_CTX *ssl_ctx, int mode) {
3535
return NULL;
3636
}
3737

38-
BIO *frag_bio = BIO_new(BIO_f_frag());
39-
if (frag_bio == NULL) {
40-
DEBUG("Cannot create frag bio");
41-
return NULL;
42-
}
38+
// BIO *frag_bio = BIO_new(BIO_f_frag());
39+
// if (frag_bio == NULL) {
40+
// DEBUG("Cannot create frag bio");
41+
// return NULL;
42+
// }
4343

44-
BIO *wmem_bio = BIO_new(BIO_s_mem());
45-
if (wmem_bio == NULL) {
46-
DEBUG("Cannot create write mem bio");
47-
return NULL;
48-
}
44+
// BIO *wmem_bio = BIO_new(BIO_s_mem());
45+
// if (wmem_bio == NULL) {
46+
// DEBUG("Cannot create write mem bio");
47+
// return NULL;
48+
// }
4949

50-
BIO *wchain = BIO_push(frag_bio, wmem_bio);
50+
// BIO *wchain = BIO_push(frag_bio, wmem_bio);
5151

5252
BIO *rmem_bio = BIO_new(BIO_s_mem());
5353
if (rmem_bio == NULL) {
5454
DEBUG("Cannot create read mem bio");
5555
return NULL;
5656
}
5757

58-
SSL_set_bio(ssl, rmem_bio, wchain);
58+
BIO *rbio = BIO_new(BIO_s_dgram_mem());
59+
if (rbio == NULL) {
60+
DEBUG("Cannot create read dgram mem bio");
61+
return NULL;
62+
}
63+
64+
BIO *wbio = BIO_new(BIO_s_dgram_mem());
65+
if (wbio == NULL) {
66+
DEBUG("Cannot create write dgram mem bio");
67+
return NULL;
68+
}
69+
70+
// SSL_set_bio(ssl, rmem_bio, wchain);
71+
SSL_set_bio(ssl, rbio, wbio);
5972

6073
// printf("Setting MTU to 1000\n");
6174
// if (SSL_set_mtu(ssl, 1500) == 0) {
6275
// return NULL;
6376
// }
6477

65-
6678
return ssl;
6779
}
6880

c_src/ex_dtls/native.c

Lines changed: 144 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
#include "dyn_buff.h"
88
#include "native.h"
99

10+
struct Datagram {
11+
UnifexPayload *packet;
12+
struct Datagram *next;
13+
};
14+
1015
static void ssl_info_cb(const SSL *ssl, int where, int ret);
1116
static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx);
12-
static int read_pending_data(UnifexPayload *gen_packets, int pending_data_len,
13-
State *state);
17+
static void read_pending_data(UnifexPayload ***payloads, int *size,
18+
State *state);
1419
static void cert_to_payload(UnifexEnv *env, X509 *x509, UnifexPayload *payload);
1520
static void pkey_to_payload(UnifexEnv *env, EVP_PKEY *pkey,
1621
UnifexPayload *payload);
@@ -21,6 +26,7 @@ UNIFEX_TERM handle_regular_read(State *state, char data[], int ret);
2126
UNIFEX_TERM handle_read_error(State *state, int ret);
2227
UNIFEX_TERM handle_handshake_in_progress(State *state, int ret);
2328
UNIFEX_TERM handle_handshake_finished(State *state);
29+
static UnifexPayload **to_payload_array(struct Datagram *dgram_list, int len);
2430

2531
int handle_load(UnifexEnv *env, void **priv_data) {
2632
UNIFEX_UNUSED(env);
@@ -242,23 +248,19 @@ UNIFEX_TERM do_handshake(UnifexEnv *env, State *state) {
242248
if (pending_data_len > 0) {
243249
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
244250

245-
char *pending_data = (char *)malloc(pending_data_len * sizeof(char));
246-
memset(pending_data, 0, pending_data_len);
247-
BIO *wbio = SSL_get_wbio(state->ssl);
248-
int read_bytes = BIO_read(wbio, pending_data, pending_data_len);
249-
if (read_bytes <= 0) {
250-
DEBUG("WBIO: read error");
251+
UnifexPayload **gen_packets;
252+
int gen_packets_size;
253+
read_pending_data(&gen_packets, &gen_packets_size, state);
254+
255+
if (gen_packets == NULL) {
251256
return unifex_raise(state->env, "Handshake failed: write BIO error");
252257
} else {
253-
DEBUG("WBIO: read: %d bytes", read_bytes);
254-
UnifexPayload gen_packets;
255-
unifex_payload_alloc(env, UNIFEX_PAYLOAD_BINARY, pending_data_len,
256-
&gen_packets);
257-
memcpy(gen_packets.data, pending_data, pending_data_len);
258-
gen_packets.size = (unsigned int)pending_data_len;
259258
int timeout = get_timeout(state->ssl);
260-
UNIFEX_TERM res_term = do_handshake_result(env, &gen_packets, timeout);
261-
unifex_payload_release(&gen_packets);
259+
UNIFEX_TERM res_term =
260+
do_handshake_result(env, gen_packets, gen_packets_size, timeout);
261+
for (int i = 0; i < gen_packets_size; i++) {
262+
unifex_payload_release(gen_packets[i]);
263+
}
262264
return res_term;
263265
}
264266
}
@@ -285,19 +287,21 @@ UNIFEX_TERM write_data(UnifexEnv *env, State *state, UnifexPayload *payload) {
285287
return unifex_raise(env, "No data to read from BIO after writing");
286288
}
287289

288-
UnifexPayload res_payload;
289-
unifex_payload_alloc(env, UNIFEX_PAYLOAD_BINARY, pending_data_len, &res_payload);
290-
291-
int read_bytes = BIO_read(wbio, res_payload.data, pending_data_len);
292-
if (read_bytes <= 0 || (size_t) read_bytes != pending_data_len) {
290+
UnifexPayload **gen_packets = NULL;
291+
int gen_packets_size = 0;
292+
read_pending_data(&gen_packets, &gen_packets_size, state);
293+
if (gen_packets == NULL) {
293294
DEBUG("Unable to read data from BIO after writing");
294295
return unifex_raise(env, "Unable to read data from BIO after writing");
295296
}
296297

297-
DEBUG("Wrote %d bytes of data", read_bytes);
298-
res_payload.size = (unsigned int) pending_data_len;
299-
UNIFEX_TERM res_term = write_data_result_ok(env, &res_payload);
300-
unifex_payload_release(&res_payload);
298+
UNIFEX_TERM res_term =
299+
write_data_result_ok(env, gen_packets, gen_packets_size);
300+
301+
for (int i = 0; i < gen_packets_size; i++) {
302+
unifex_payload_release(gen_packets[i]);
303+
}
304+
301305
return res_term;
302306
}
303307

@@ -333,12 +337,14 @@ UNIFEX_TERM handle_data(UnifexEnv *env, State *state, UnifexPayload *payload) {
333337

334338
UNIFEX_TERM handle_regular_read(State *state, char data[], int ret) {
335339
if (ret > 0) {
336-
UnifexPayload packets;
337-
unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, ret, &packets);
338-
memcpy(packets.data, data, ret);
339-
packets.size = (unsigned int)ret;
340-
UNIFEX_TERM res_term = handle_data_result_ok(state->env, &packets);
341-
unifex_payload_release(&packets);
340+
UnifexPayload **packets = calloc(1, sizeof(UnifexPayload *));
341+
UnifexPayload packet;
342+
packets[0] = &packet;
343+
unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, ret, packets[0]);
344+
memcpy(packets[0]->data, data, ret);
345+
packets[0]->size = (unsigned int)ret;
346+
UNIFEX_TERM res_term = handle_data_result_ok(state->env, packets, 1);
347+
unifex_payload_release(packets[0]);
342348
return res_term;
343349
}
344350

@@ -369,7 +375,8 @@ UNIFEX_TERM handle_read_error(State *state, int ret) {
369375

370376
UNIFEX_TERM handle_handshake_finished(State *state) {
371377
UNIFEX_TERM res_term;
372-
UnifexPayload gen_packets;
378+
UnifexPayload **gen_packets = NULL;
379+
int gen_packets_size = 0;
373380
KeyingMaterial *keying_material = export_keying_material(state->ssl);
374381
if (keying_material == NULL) {
375382
DEBUG("Cannot export keying material");
@@ -393,10 +400,9 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
393400
size_t pending_data_len = BIO_ctrl_pending(SSL_get_wbio(state->ssl));
394401
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
395402

396-
unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, pending_data_len,
397-
&gen_packets);
398403
if (pending_data_len > 0) {
399-
if (read_pending_data(&gen_packets, pending_data_len, state) < 0) {
404+
read_pending_data(&gen_packets, &gen_packets_size, state);
405+
if (gen_packets == NULL) {
400406
res_term = unifex_raise(state->env, "Handshake failed: write BIO error");
401407
goto cleanup;
402408
}
@@ -416,10 +422,14 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
416422

417423
res_term = handle_data_result_handshake_finished(
418424
state->env, local_keying_material, remote_keying_material,
419-
keying_material->protection_profile, &gen_packets);
425+
keying_material->protection_profile, gen_packets, gen_packets_size);
420426

421427
cleanup:
422-
unifex_payload_release(&gen_packets);
428+
429+
for (int i = 0; i < gen_packets_size; i++) {
430+
unifex_payload_release(gen_packets[i]);
431+
}
432+
423433
unifex_payload_release(&client_keying_material);
424434
unifex_payload_release(&server_keying_material);
425435
return res_term;
@@ -434,16 +444,20 @@ UNIFEX_TERM handle_handshake_in_progress(State *state, int ret) {
434444
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
435445

436446
if (pending_data_len > 0) {
437-
UnifexPayload gen_packets;
438-
unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, pending_data_len,
439-
&gen_packets);
440-
if (read_pending_data(&gen_packets, pending_data_len, state) < 0) {
447+
UnifexPayload **gen_packets = NULL;
448+
int gen_packets_size = 0;
449+
read_pending_data(&gen_packets, &gen_packets_size, state);
450+
if (gen_packets == NULL) {
441451
return unifex_raise(state->env, "Handshake failed: write BIO error");
442452
}
443453
int timeout = get_timeout(state->ssl);
444454
UNIFEX_TERM res_term = handle_data_result_handshake_packets(
445-
state->env, &gen_packets, timeout);
446-
unifex_payload_release(&gen_packets);
455+
state->env, gen_packets, gen_packets_size, timeout);
456+
457+
for (int i = 0; i < gen_packets_size; i++) {
458+
unifex_payload_release(gen_packets[i]);
459+
}
460+
447461
return res_term;
448462
} else {
449463
return handle_data_result_handshake_want_read(state->env);
@@ -458,20 +472,22 @@ UNIFEX_TERM handle_timeout(UnifexEnv *env, State *state) {
458472
if (result != 1)
459473
return handle_timeout_result_ok(env);
460474

461-
BIO *wbio = SSL_get_wbio(state->ssl);
462-
size_t pending_data_len = BIO_ctrl_pending(wbio);
463-
UnifexPayload gen_packets;
464-
unifex_payload_alloc(env, UNIFEX_PAYLOAD_BINARY, pending_data_len,
465-
&gen_packets);
475+
UnifexPayload **gen_packets = NULL;
476+
int gen_packets_size = 0;
477+
read_pending_data(&gen_packets, &gen_packets_size, state);
466478

467-
if (read_pending_data(&gen_packets, pending_data_len, state) < 0) {
479+
if (gen_packets == NULL) {
468480
return unifex_raise(state->env,
469481
"Retransmit handshake failed: write BIO error");
470482
} else {
471483
int timeout = get_timeout(state->ssl);
472-
UNIFEX_TERM res_term =
473-
handle_timeout_result_retransmit(env, &gen_packets, timeout);
474-
unifex_payload_release(&gen_packets);
484+
UNIFEX_TERM res_term = handle_timeout_result_retransmit(
485+
env, gen_packets, gen_packets_size, timeout);
486+
487+
for (int i = 0; i < gen_packets_size; i++) {
488+
unifex_payload_release(gen_packets[i]);
489+
}
490+
475491
return res_term;
476492
}
477493
}
@@ -511,22 +527,84 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
511527
}
512528
}
513529

514-
static int read_pending_data(UnifexPayload *gen_packets, int pending_data_len,
515-
State *state) {
516-
char *pending_data = (char *)malloc(pending_data_len * sizeof(char));
517-
memset(pending_data, 0, pending_data_len);
518-
BIO *wbio = SSL_get_wbio(state->ssl);
519-
int read_bytes = BIO_read(wbio, pending_data, pending_data_len);
520-
if (read_bytes <= 0) {
521-
DEBUG("WBIO: read error");
522-
} else {
523-
DEBUG("WBIO: read: %d bytes", read_bytes);
524-
memcpy(gen_packets->data, pending_data, pending_data_len);
525-
gen_packets->size = (unsigned int)pending_data_len;
530+
static UnifexPayload **to_payload_array(struct Datagram *dgram_list, int len) {
531+
532+
UnifexPayload **payloads = calloc(len, sizeof(UnifexPayload *));
533+
534+
for (int i = 0; i < len; i++) {
535+
DEBUG("%d", i);
536+
payloads[i] = NULL;
537+
}
538+
539+
struct Datagram *itr = dgram_list;
540+
541+
for (int i = 0; i < len; i++) {
542+
DEBUG("size, %d", itr->packet->size);
543+
itr = itr->next;
544+
}
545+
546+
itr = dgram_list;
547+
for (int i = 0; i < len; i++) {
548+
DEBUG("to payload array 3, %d", len);
549+
payloads[i] = itr->packet;
550+
itr = itr->next;
551+
}
552+
553+
DEBUG("to payload array");
554+
555+
// itr = dgram_list;
556+
// struct Datagram *next = dgram_list->next;
557+
558+
// for (int i = 0; i < len; i++) {
559+
// free(itr);
560+
// itr = next;
561+
// next = itr->next;
562+
// DEBUG("dupa2");
563+
// }
564+
565+
return payloads;
566+
}
567+
568+
static void read_pending_data(UnifexPayload ***payloads, int *size,
569+
State *state) {
570+
571+
struct Datagram *dgram_list = NULL;
572+
struct Datagram *itr = NULL;
573+
*size = 0;
574+
575+
size_t pending_data_len = 0;
576+
while ((pending_data_len = BIO_ctrl_pending(SSL_get_wbio(state->ssl))) > 0) {
577+
struct Datagram *dgram = calloc(1, sizeof(struct Datagram));
578+
UnifexPayload *payload = calloc(1, sizeof(UnifexPayload));
579+
unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, pending_data_len,
580+
payload);
581+
dgram->packet = payload;
582+
dgram->next = NULL;
583+
584+
BIO *wbio = SSL_get_wbio(state->ssl);
585+
int read_bytes = BIO_read(wbio, payload->data, pending_data_len);
586+
if (read_bytes <= 0) {
587+
DEBUG("WBIO: read error");
588+
// TODO cleanup
589+
*size = 0;
590+
return;
591+
} else {
592+
DEBUG("WBIO: read: %d bytes", read_bytes);
593+
dgram->packet->size = (unsigned int)pending_data_len;
594+
}
595+
596+
if (dgram_list == NULL) {
597+
dgram_list = dgram;
598+
itr = dgram_list;
599+
} else {
600+
itr->next = dgram;
601+
itr = itr->next;
602+
}
603+
604+
(*size)++;
526605
}
527-
free(pending_data);
528606

529-
return read_bytes;
607+
*payloads = to_payload_array(dgram_list, *size);
530608
}
531609

532610
static void cert_to_payload(UnifexEnv *env, X509 *x509,

c_src/ex_dtls/native.spec.exs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ spec get_peer_cert(state) :: payload | (nil :: label)
2121

2222
spec get_cert_fingerprint(payload) :: payload
2323

24-
spec do_handshake(state) :: {packets :: payload, timeout :: int}
24+
spec do_handshake(state) :: {packets :: [payload], timeout :: int}
2525

26-
spec handle_timeout(state) :: (:ok :: label) | {:retransmit :: label, packets :: payload, timeout :: int}
26+
spec handle_timeout(state) :: (:ok :: label) | {:retransmit :: label, packets :: [payload], timeout :: int}
2727

28-
spec write_data(state, packets :: payload) :: {:ok :: label, packets :: payload} | {:error :: label, :handshake_not_finished :: label}
28+
spec write_data(state, packets :: payload) :: {:ok :: label, packets :: [payload]} | {:error :: label, :handshake_not_finished :: label}
2929

3030
spec handle_data(state, packets :: payload) ::
31-
{:ok :: label, packets :: payload}
31+
{:ok :: label, packets :: [payload]}
3232
| (:handshake_want_read :: label)
33-
| {:handshake_packets :: label, packets :: payload, timeout :: int}
33+
| {:handshake_packets :: label, packets :: [payload], timeout :: int}
3434
| {:handshake_finished :: label, client_keying_material :: payload,
35-
server_keying_material :: payload, protection_profile :: int, packets :: payload}
35+
server_keying_material :: payload, protection_profile :: int, packets :: [payload]}
3636
| {:error :: label, :peer_closed_for_writing :: label}
3737
| {:error :: label, :handshake_error :: label
3838
}

0 commit comments

Comments
 (0)