Skip to content

Instantly share code, notes, and snippets.

@colmmacc
Created August 12, 2016 18:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save colmmacc/769453e7c1fe47498eafdfa6459e59ee to your computer and use it in GitHub Desktop.
Save colmmacc/769453e7c1fe47498eafdfa6459e59ee to your computer and use it in GitHub Desktop.
diff --git a/tls/s2n_connection.c b/tls/s2n_connection.c
index 27a9c04..8a3f42e 100644
--- a/tls/s2n_connection.c
+++ b/tls/s2n_connection.c
@@ -206,6 +206,7 @@ int s2n_connection_wipe(struct s2n_connection *conn)
conn->mode = mode;
conn->config = config;
conn->close_notify_queued = 0;
+ conn->current_user_data_consumed = 0;
conn->initial.cipher_suite = &s2n_null_cipher_suite;
conn->secure.cipher_suite = &s2n_null_cipher_suite;
conn->server = &conn->initial;
diff --git a/tls/s2n_connection.h b/tls/s2n_connection.h
index 09a127e..a8115c3 100644
--- a/tls/s2n_connection.h
+++ b/tls/s2n_connection.h
@@ -95,6 +95,11 @@ struct s2n_connection {
/* How big is the record we are actively reading? */
uint16_t current_in_record_size;
+ /* How much of the current user buffer have we already
+ * encrypted and have pending for the wire.
+ */
+ uint16_t current_user_data_consumed;
+
/* An alert may be fragmented across multiple records,
* this stuffer is used to re-assemble.
*/
diff --git a/tls/s2n_record_write.c b/tls/s2n_record_write.c
index b060eeb..fa4245e 100644
--- a/tls/s2n_record_write.c
+++ b/tls/s2n_record_write.c
@@ -253,6 +253,7 @@ int s2n_record_write(struct s2n_connection *conn, uint8_t content_type, struct s
}
conn->wire_bytes_out += actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH;
+ conn->current_user_data_consumed += data_bytes_to_take;
return data_bytes_to_take;
}
diff --git a/tls/s2n_send.c b/tls/s2n_send.c
index 545639f..59746c0 100644
--- a/tls/s2n_send.c
+++ b/tls/s2n_send.c
@@ -49,6 +49,8 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
}
conn->wire_bytes_out += w;
}
+ conn->current_user_buffer_consumed = 0;
+
if (conn->closing) {
conn->closed = 1;
/* Delay wiping for close_notify. s2n_shutdown() needs to wait for peer's close_notify */
@@ -91,8 +93,6 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
ssize_t s2n_send(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked)
{
- struct s2n_blob in = {.data = buf };
- ssize_t bytes_written = 0;
int max_payload_size;
int w;
@@ -119,8 +119,9 @@ ssize_t s2n_send(struct s2n_connection * conn, void *buf, ssize_t size, s2n_bloc
}
/* Now write the data we were asked to send this round */
- while (size) {
- in.size = MIN(size, max_payload_size);
+ while (size - conn->current_user_buffer_consumed) {
+ struct s2n_blob in = {.data = buf + conn->current_user_buffer_consumed};
+ in.size = MIN(size - conn->current_user_buffer_consumed, max_payload_size);
/* Don't split messages in server mode for interoperability with naive clients.
* Some clients may have expectations based on the amount of content in the first record.
@@ -136,29 +137,11 @@ ssize_t s2n_send(struct s2n_connection * conn, void *buf, ssize_t size, s2n_bloc
GUARD(s2n_stuffer_rewrite(&conn->out));
GUARD(s2n_record_write(conn, TLS_APPLICATION_DATA, &in));
- bytes_written += in.size;
-
/* Send it */
- while (s2n_stuffer_data_available(&conn->out)) {
- errno = 0;
- w = s2n_stuffer_send_to_fd(&conn->out, conn->writefd, s2n_stuffer_data_available(&conn->out));
- if (w < 0) {
- if (errno == EWOULDBLOCK) {
- if (bytes_written) {
- return bytes_written;
- }
- S2N_ERROR(S2N_ERR_BLOCKED);
- }
- S2N_ERROR(S2N_ERR_IO);
- }
- conn->wire_bytes_out += w;
- }
-
- in.data += in.size;
- size -= in.size;
+ GUARD(s2n_flush(conn, blocked));
}
*blocked = S2N_NOT_BLOCKED;
- return bytes_written;
+ return size;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment