Skip to content

Commit ae0df71

Browse files
committed
Refactor read_pending_data and remove unneeded BIO_ctrl_pending calls
1 parent aa5a7e9 commit ae0df71

File tree

1 file changed

+43
-57
lines changed

1 file changed

+43
-57
lines changed

c_src/ex_dtls/native.c

Lines changed: 43 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ struct Datagram {
1414

1515
static void ssl_info_cb(const SSL *ssl, int where, int ret);
1616
static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx);
17-
static void read_pending_data(UnifexPayload ***payloads, int *size,
18-
State *state);
17+
static int read_pending_data(UnifexPayload ***payloads, int *size,
18+
State *state);
1919
static void cert_to_payload(UnifexEnv *env, X509 *x509, UnifexPayload *payload);
2020
static void pkey_to_payload(UnifexEnv *env, EVP_PKEY *pkey,
2121
UnifexPayload *payload);
@@ -245,27 +245,23 @@ UNIFEX_TERM get_cert_fingerprint(UnifexEnv *env, UnifexPayload *cert) {
245245
UNIFEX_TERM do_handshake(UnifexEnv *env, State *state) {
246246
SSL_do_handshake(state->ssl);
247247

248-
size_t pending_data_len = BIO_ctrl_pending(SSL_get_wbio(state->ssl));
249-
if (pending_data_len > 0) {
250-
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
251-
252-
UnifexPayload **gen_packets;
253-
int gen_packets_size;
254-
read_pending_data(&gen_packets, &gen_packets_size, state);
248+
UnifexPayload **gen_packets;
249+
int gen_packets_size;
250+
int ret = read_pending_data(&gen_packets, &gen_packets_size, state);
255251

256-
if (gen_packets == NULL) {
257-
return unifex_raise(state->env, "Handshake failed: write BIO error");
258-
} else {
259-
int timeout = get_timeout(state->ssl);
260-
UNIFEX_TERM res_term =
261-
do_handshake_result(env, gen_packets, gen_packets_size, timeout);
262-
free_payload_array(gen_packets, gen_packets_size);
252+
if (ret == 0 && (gen_packets == NULL || gen_packets_size == 0)) {
253+
return unifex_raise(state->env, "Handshake failed: no packets generated");
254+
} else if (ret < 0) {
255+
return unifex_raise(state->env,
256+
"Handshake failed: couldn't read pending data");
257+
} else {
258+
int timeout = get_timeout(state->ssl);
259+
UNIFEX_TERM res_term =
260+
do_handshake_result(env, gen_packets, gen_packets_size, timeout);
261+
free_payload_array(gen_packets, gen_packets_size);
263262

264-
return res_term;
265-
}
263+
return res_term;
266264
}
267-
268-
return unifex_raise(state->env, "Handshake failed: no packets generated");
269265
}
270266

271267
UNIFEX_TERM write_data(UnifexEnv *env, State *state, UnifexPayload *payload) {
@@ -290,7 +286,7 @@ UNIFEX_TERM write_data(UnifexEnv *env, State *state, UnifexPayload *payload) {
290286
UnifexPayload **gen_packets = NULL;
291287
int gen_packets_size = 0;
292288
read_pending_data(&gen_packets, &gen_packets_size, state);
293-
if (gen_packets == NULL) {
289+
if (gen_packets == NULL || gen_packets_size == 0) {
294290
DEBUG("Unable to read data from BIO after writing");
295291
return unifex_raise(env, "Unable to read data from BIO after writing");
296292
}
@@ -394,16 +390,12 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
394390
memcpy(server_keying_material.data, keying_material->server, len);
395391
server_keying_material.size = len;
396392

397-
size_t pending_data_len = BIO_ctrl_pending(SSL_get_wbio(state->ssl));
398-
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
399-
400-
if (pending_data_len > 0) {
401-
read_pending_data(&gen_packets, &gen_packets_size, state);
402-
if (gen_packets == NULL) {
403-
res_term = unifex_raise(state->env, "Handshake failed: write BIO error");
404-
goto cleanup;
405-
}
393+
int ret = read_pending_data(&gen_packets, &gen_packets_size, state);
394+
if (ret < 0) {
395+
res_term = unifex_raise(state->env, "Handshake failed: write BIO error");
396+
goto cleanup;
406397
}
398+
407399
state->hsk_finished = 1;
408400

409401
UnifexPayload *local_keying_material;
@@ -422,9 +414,7 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
422414
keying_material->protection_profile, gen_packets, gen_packets_size);
423415

424416
cleanup:
425-
426417
free_payload_array(gen_packets, gen_packets_size);
427-
428418
unifex_payload_release(&client_keying_material);
429419
unifex_payload_release(&server_keying_material);
430420
return res_term;
@@ -435,25 +425,22 @@ UNIFEX_TERM handle_handshake_in_progress(State *state, int ret) {
435425
switch (ssl_error) {
436426
case SSL_ERROR_WANT_READ:
437427
DEBUG("SSL WANT READ");
438-
size_t pending_data_len = BIO_ctrl_pending(SSL_get_wbio(state->ssl));
439-
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
428+
UnifexPayload **gen_packets = NULL;
429+
int gen_packets_size = 0;
430+
int read_err = read_pending_data(&gen_packets, &gen_packets_size, state);
440431

441-
if (pending_data_len > 0) {
442-
UnifexPayload **gen_packets = NULL;
443-
int gen_packets_size = 0;
444-
read_pending_data(&gen_packets, &gen_packets_size, state);
445-
if (gen_packets == NULL) {
446-
return unifex_raise(state->env, "Handshake failed: write BIO error");
447-
}
432+
if (read_err < 0) {
433+
return unifex_raise(state->env, "Handshake failed: write BIO error");
434+
} else if (read_err == 0 && gen_packets_size == 0) {
435+
return handle_data_result_handshake_want_read(state->env);
436+
} else {
448437
int timeout = get_timeout(state->ssl);
449438
UNIFEX_TERM res_term = handle_data_result_handshake_packets(
450439
state->env, gen_packets, gen_packets_size, timeout);
451440

452441
free_payload_array(gen_packets, gen_packets_size);
453442

454443
return res_term;
455-
} else {
456-
return handle_data_result_handshake_want_read(state->env);
457444
}
458445
default:
459446
return handle_read_error(state, ret);
@@ -469,7 +456,7 @@ UNIFEX_TERM handle_timeout(UnifexEnv *env, State *state) {
469456
int gen_packets_size = 0;
470457
read_pending_data(&gen_packets, &gen_packets_size, state);
471458

472-
if (gen_packets == NULL) {
459+
if (gen_packets == NULL || gen_packets_size == 0) {
473460
return unifex_raise(state->env,
474461
"Retransmit handshake failed: write BIO error");
475462
} else {
@@ -517,21 +504,14 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
517504
}
518505

519506
static UnifexPayload **to_payload_array(struct Datagram *dgram_list, int len) {
507+
if (len == 0) {
508+
return NULL;
509+
}
520510

521511
UnifexPayload **payloads = calloc(len, sizeof(UnifexPayload *));
522512

523-
for (int i = 0; i < len; i++) {
524-
DEBUG("%d", i);
525-
payloads[i] = NULL;
526-
}
527-
528513
struct Datagram *itr = dgram_list;
529514

530-
for (int i = 0; i < len; i++) {
531-
itr = itr->next;
532-
}
533-
534-
itr = dgram_list;
535515
for (int i = 0; i < len; i++) {
536516
payloads[i] = itr->packet;
537517
itr = itr->next;
@@ -553,15 +533,16 @@ static UnifexPayload **to_payload_array(struct Datagram *dgram_list, int len) {
553533
return payloads;
554534
}
555535

556-
static void read_pending_data(UnifexPayload ***payloads, int *size,
557-
State *state) {
536+
static int read_pending_data(UnifexPayload ***payloads, int *size,
537+
State *state) {
558538

559539
struct Datagram *dgram_list = NULL;
560540
struct Datagram *itr = NULL;
561541
*size = 0;
562542

563543
size_t pending_data_len = 0;
564544
while ((pending_data_len = BIO_ctrl_pending(SSL_get_wbio(state->ssl))) > 0) {
545+
DEBUG("WBIO: pending data: %ld bytes", pending_data_len);
565546
struct Datagram *dgram = calloc(1, sizeof(struct Datagram));
566547
UnifexPayload *payload = calloc(1, sizeof(UnifexPayload));
567548
unifex_payload_alloc(state->env, UNIFEX_PAYLOAD_BINARY, pending_data_len,
@@ -598,7 +579,7 @@ static void read_pending_data(UnifexPayload ***payloads, int *size,
598579

599580
*size = 0;
600581
*payloads = NULL;
601-
return;
582+
return -1;
602583
} else {
603584
DEBUG("WBIO: read: %d bytes", read_bytes);
604585
dgram->packet->size = (unsigned int)pending_data_len;
@@ -616,6 +597,7 @@ static void read_pending_data(UnifexPayload ***payloads, int *size,
616597
}
617598

618599
*payloads = to_payload_array(dgram_list, *size);
600+
return 0;
619601
}
620602

621603
static void cert_to_payload(UnifexEnv *env, X509 *x509,
@@ -637,6 +619,10 @@ static void pkey_to_payload(UnifexEnv *env, EVP_PKEY *pkey,
637619
}
638620

639621
static void free_payload_array(UnifexPayload **payloads, int len) {
622+
if (payloads == NULL) {
623+
return;
624+
}
625+
640626
for (int i = 0; i < len; i++) {
641627
unifex_payload_release(payloads[i]);
642628
free(payloads[i]);

0 commit comments

Comments
 (0)