Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS: TCP_CORK equivalent #9846

Open
bryghtlabs-richard opened this issue Dec 12, 2024 · 0 comments
Open

TLS: TCP_CORK equivalent #9846

bryghtlabs-richard opened this issue Dec 12, 2024 · 0 comments

Comments

@bryghtlabs-richard
Copy link

Suggested enhancement

TCP_CORK equivalent for MbedTLS.

//mbedtls_ssl_context is extended to include a corking_count integer
mbedtls_ssl_corking (mbedtls_ssl_context *ssl);//Increment corking_count
mbedtls_ssl_push (mbedtls_ssl_context *ssl);//Decrement corking_count, flush buffer iff corking_count == 0

Once mbedtls_ssl_corking() is called, calls to mbedtls_ssl_write() that fit in the TLS write-buffer will be appended to the TLS write-buffer. Once the write-buffer becomes full, or full enough that the next write won't fit, the write-buffer will be encrypted and sent to the next layer for transport.

When mbedtls_ssl_push() is called the same number of times as mbedtls_ssl_corking(), and remaining bytes in the MbedTLS write buffer are encrypted and sent to the next layer for transport.

Justification

Mbed TLS needs this because sequences of small writes over TLS becomes sequences of small TCP packets with a lot of TLS overhead per mbedtls_ssl_write() call.

One example of this is a WebSocket client - each time application wants to write a payload string over a WebSocket, the WebSocket layer needs to mbedtls_ssl_write(WebSocketHeader), then mbedtls_ssl_write(WebSocketPayloadString). Currently, these become two TLS blocks, and depending on TCP send buffer state and Nagling, often the header will be sent first, wait for the TCP ACK, then send the payload.

Another example of this is HTTP1.1 request pipelining - each time the application submits a request through mbed_ssl_write(HTTP request), it's broken into its own TLS block, and its own TCP segment .

Maintaining a corking_count instead of a corking bit/mode is useful for applications like WebSockets where an application may know that it is about to send several small WebSocket frames back to back. Example pseudocode:

sendWsFrame(mbedtls_ssl_context *ssl, const char * payload) {
  wsHeader = buildHeader(strlen(payload));
  mbedtls_ssl_corking(ssl);
  mbedtls_ssl_write(ssl, &wsHeader[0], wsHeader.size());
  mbedtls_ssl_write(ssl, payload, strlen(payload));
  mbedtls_ssl_push(ssl);
}

exampleAppSend1(mbedtls_ssl_context *ssl){
  //Send one WS frame in one TLS block
  sendWsFrame(ssl, "Hello World");
}

exampleAppSendMany(mbedtls_ssl_context *ssl){
  //Send many WS frame in minimum number of TLS frames
  mbedtls_ssl_corking(ssl);
  sendWsFrame(ssl, "H");
  sendWsFrame(ssl, "e");
  sendWsFrame(ssl, "l");
  sendWsFrame(ssl, "l");
  sendWsFrame(ssl, "o");
  sendWsFrame(ssl, " ");
  sendWsFrame(ssl, "W");
  sendWsFrame(ssl, "o");
  sendWsFrame(ssl, "r");
  sendWsFrame(ssl, "l");
  sendWsFrame(ssl, "d");
  mbedtls_ssl_push(ssl);
}

My apologies if there is already a way to achieve this behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants