struct wait_event *recv_wait;
struct wait_event *send_wait;
int xprt_st; /* transport layer state, initialized to zero */
- int tmp_early_data; /* 1st byte of early data, if any */
+ struct buffer early_buf; /* buffer to store the early data received */
int sent_early_data; /* Amount of early data we sent so far */
};
ctx->wait_event.tasklet->context = ctx;
ctx->wait_event.events = 0;
ctx->sent_early_data = 0;
- ctx->tmp_early_data = -1;
+ ctx->early_buf = BUF_NULL;
ctx->conn = conn;
ctx->send_wait = NULL;
ctx->recv_wait = NULL;
goto err;
}
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
- if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data)
- SSL_set_max_early_data(ctx->ssl, global.tune.bufsize - global.tune.maxrewrite);
+ if (__objt_listener(conn->target)->bind_conf->ssl_conf.early_data) {
+ b_alloc(&ctx->early_buf);
+ SSL_set_max_early_data(ctx->ssl,
+ /* Only allow early data if we managed to allocate
+ * a buffer.
+ */
+ (!b_is_null(&ctx->early_buf)) ?
+ global.tune.bufsize - global.tune.maxrewrite : 0);
+ }
#endif
ctx->bio = BIO_new(ha_meth);
* detect early data, except to try to read them
*/
if (conn->flags & CO_FL_EARLY_SSL_HS) {
- size_t read_data;
-
- ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
- 1, &read_data);
- if (ret == SSL_READ_EARLY_DATA_ERROR)
- goto check_error;
- if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
- conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
- return 1;
- } else
- conn->flags &= ~CO_FL_EARLY_SSL_HS;
+ size_t read_data = 0;
+
+ while (1) {
+ ret = SSL_read_early_data(ctx->ssl,
+ b_tail(&ctx->early_buf), b_room(&ctx->early_buf),
+ &read_data);
+ if (ret == SSL_READ_EARLY_DATA_ERROR)
+ goto check_error;
+ if (read_data > 0) {
+ conn->flags |= CO_FL_EARLY_DATA;
+ b_add(&ctx->early_buf, read_data);
+ }
+ if (ret == SSL_READ_EARLY_DATA_FINISH) {
+ conn->flags &= ~CO_FL_EARLY_SSL_HS;
+ if (!b_data(&ctx->early_buf))
+ b_free(&ctx->early_buf);
+ break;
+ }
+ }
}
#endif
/* If we use SSL_do_handshake to process a reneg initiated by
return NULL;
}
}
+#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
+ /* If we have early data and somebody wants to receive, let them */
+ else if (b_data(&ctx->early_buf) && ctx->recv_wait) {
+ ctx->recv_wait->events &= ~SUB_RETRY_RECV;
+ tasklet_wakeup(ctx->recv_wait->tasklet);
+ ctx->recv_wait = NULL;
+
+ }
+#endif
return NULL;
}
if (!ctx)
goto out_error;
+#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
+ if (b_data(&ctx->early_buf)) {
+ try = b_contig_space(buf);
+ if (try > b_data(&ctx->early_buf))
+ try = b_data(&ctx->early_buf);
+ memcpy(b_tail(buf), b_head(&ctx->early_buf), try);
+ b_add(buf, try);
+ b_del(&ctx->early_buf, try);
+ if (b_data(&ctx->early_buf) == 0)
+ b_free(&ctx->early_buf);
+ return try;
+ }
+#endif
+
if (conn->flags & CO_FL_HANDSHAKE)
/* a handshake was requested */
return 0;
if (try > count)
try = count;
- if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
- ctx->tmp_early_data != -1) {
- *b_tail(buf) = ctx->tmp_early_data;
- done++;
- try--;
- count--;
- b_add(buf, 1);
- ctx->tmp_early_data = -1;
- continue;
- }
-
-#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
- if (conn->flags & CO_FL_EARLY_SSL_HS) {
- size_t read_length;
-
- ret = SSL_read_early_data(ctx->ssl,
- b_tail(buf), try, &read_length);
- if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
- read_length > 0)
- conn->flags |= CO_FL_EARLY_DATA;
- if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
- ret == SSL_READ_EARLY_DATA_FINISH) {
- if (ret == SSL_READ_EARLY_DATA_FINISH) {
- /*
- * We're done reading the early data,
- * let's make the handshake
- */
- conn->flags &= ~CO_FL_EARLY_SSL_HS;
- conn->flags |= CO_FL_SSL_WAIT_HS;
- need_out = 1;
- /* Now initiate the handshake */
- tasklet_wakeup(ctx->wait_event.tasklet);
- if (read_length == 0)
- break;
- }
- ret = read_length;
- }
- } else
-#endif
ret = SSL_read(ctx->ssl, b_tail(buf), try);
if (conn->flags & CO_FL_ERROR) {
}
#endif
SSL_free(ctx->ssl);
+ b_free(&ctx->early_buf);
tasklet_free(ctx->wait_event.tasklet);
pool_free(ssl_sock_ctx_pool, ctx);
_HA_ATOMIC_SUB(&sslconns, 1);