*/
#include "quic_conn.h"
+#include "lib/log.h"
#include "quic_stream.h"
#include "quic_common.h"
#include "libdnssec/random.h"
#include "worker.h"
#include <libknot/wire.h>
#include <ngtcp2/ngtcp2.h>
+#include <uv.h>
#define EPHEMERAL_CERT_EXPIRATION_SECONDS_RENEW_BEFORE ((time_t)60*60*24*7)
int64_t stream_id, uint64_t offset, const uint8_t *data,
size_t datalen, void *user_data, void *stream_user_data)
{
- (void)ngconn;
-
struct pl_quic_conn_sess_data *conn = user_data;
struct pl_quic_stream_sess_data *stream = stream_user_data;
kr_require(wire_buf_consume(&stream->pers_inbuf, datalen - sizeof(uint16_t)) == kr_ok());
}
+ /* we can ignore ret return value, it can only be ENOMEM, at which point
+ * there is nothing we can do anyway and the connection will timeout cleanly*/
+ (void)ngtcp2_conn_extend_max_stream_offset(ngconn, stream_id, datalen);
+ ngtcp2_conn_extend_max_offset(ngconn, datalen);
+
finished:
if (flags & NGTCP2_STREAM_DATA_FLAG_FIN) {
queue_push(conn->pending_unwrap, stream);
1,
false);
- kr_require(new_subsession);
+ if (!new_subsession) {
+ kr_log_error(DOQ, "Failed to create new quic stream session\n");
+ return kr_error(ENOMEM);
+ }
struct pl_quic_stream_sess_data *stream =
protolayer_sess_data_get_proto(new_subsession,
kr_require(stream);
stream->conn_ref = conn;
-
if (conn->streams_count <= 0) {
add_head(&conn->streams, &stream->list_node);
} else {
int64_t stream_id, uint64_t app_error_code,
void *user_data, void *stream_user_data)
{
- (void)ngconn;
-
+ ngtcp2_conn_extend_max_streams_bidi(ngconn, 1);
struct pl_quic_conn_sess_data *conn = user_data;
struct pl_quic_stream_sess_data *stream = stream_user_data;
rem_node(&stream->list_node);
(void)ngconn;
struct pl_quic_conn_sess_data *conn = user_data;
session2_event(conn->h.session->transport.parent,
- PROTOLAYER_EVENT_CONNECT_UPDATE,
- conn);
+ PROTOLAYER_EVENT_CONNECT_UPDATE, conn);
memcpy(cid, &conn->dcid, sizeof(ngtcp2_cid));
if (ngtcp2_crypto_generate_stateless_reset_token(token, conn->secret,
struct wire_buf *save = ctx->payload.wire_buf;
ctx->payload.wire_buf = &err_wb;
- // if (wire_buf_data_length(ctx->payload.wire_buf) != 0) {
- // wire_buf_reset(ctx->payload.wire_buf);
- // return kr_error(EINVAL);
- // }
-
uint64_t now = quic_timestamp();
ngtcp2_cid new_dcid;
} else {
ccerr.type = NGTCP2_CCERR_TYPE_APPLICATION;
}
- // ccerr.error_code = NGTCP2_ERR_HANDSHAKE_TIMEOUT;
ret = ngtcp2_conn_write_connection_close(
conn->conn, NULL, &pi,
wire_buf_free_space(ctx->payload.wire_buf),
}
}
+ uv_timer_again(&conn->h.session->timer);
ret = handle_packet(conn, ctx);
if (ret != kr_ok()) {
if (QUIC_CAN_SEND(conn)) {
conn->conn = NULL;
conn->priority = NULL;
+ conn->streams_count = 0;
conn->tls_session = NULL;
conn->server_credentials = NULL;
if (quic_generate_secret(conn->secret, sizeof(conn->secret)) != kr_ok()) {
return kr_error(EINVAL);
}
+ session2_timer_start(session, PROTOLAYER_EVENT_CONNECT_TIMEOUT,
+ QUIC_CONN_IDLE_TIMEOUT / NGTCP2_MILLISECONDS,
+ QUIC_CONN_IDLE_TIMEOUT / NGTCP2_MILLISECONDS);
+
return kr_ok();
}
kr_log_error(DOQ, "Client side of QUIC is not implemented\n");
}
-
conn->priority = NULL;
conn->tls_session = NULL;
conn->server_credentials = NULL;
struct session2 *session, void *sess_data)
{
struct pl_quic_conn_sess_data *conn = sess_data;
+ if (event == PROTOLAYER_EVENT_CONNECT_TIMEOUT) {
+ session2_event(conn->h.session->transport.parent, event, conn);
+ return PROTOLAYER_EVENT_CONSUME;
+ }
+
if (event == PROTOLAYER_EVENT_DISCONNECT ||
event == PROTOLAYER_EVENT_CLOSE ||
event == PROTOLAYER_EVENT_FORCE_CLOSE) {
--conn->streams_count;
}
session2_dec_refs(session);
+ session2_timer_stop(session);
return PROTOLAYER_EVENT_CONSUME;
}
(void)send_special(conn, ctx, DOQ_EXCESSIVE_LOAD);
}
+/* unused for now, compare performance with per conn uv_timer_t spawns */
void kr_quic_table_sweep(struct kr_quic_table *table,
struct protolayer_iter_ctx *ctx)
{
qconn = kr_quic_table_lookup(&dcid, demux->conn_table);
if (!qconn) {
/* Clear idle connections */
- kr_quic_table_sweep(demux->conn_table, ctx);
+ // kr_quic_table_sweep(demux->conn_table, ctx);
if (demux->conn_table->usage >= demux->conn_table->max_conns) {
kr_log_warning(DOQ,
"Refusing to open new connection, reached limit of active conns\n");
- /* we may inform the client that limits have been reached */
+ /* we might want to inform the client
+ * that limits have been reached */
return protolayer_break(ctx, kr_ok());
}
ngtcp2_pkt_hd header = { 0 };
- if (ngtcp2_accept(&header,
+ ret = ngtcp2_accept(&header,
wire_buf_data(ctx->payload.wire_buf),
- wire_buf_data_length(ctx->payload.wire_buf))
- != NGTCP2_NO_ERROR) {
+ wire_buf_data_length(ctx->payload.wire_buf));
+ if (ret != NGTCP2_NO_ERROR) {
+ kr_log_debug(DOQ, "error accepting new conn: %s (%d)\n",
+ ngtcp2_strerror(ret), ret);
/* either the packet is not acceptable as the first
* packet of a new connection, or the function failed
PROTOLAYER_TYPE_QUIC_CONN);
kr_quic_table_add(conn_sess_data, &dcid,
demux->conn_table);
-
qconn = conn_sess_data;
}
ctx->finished_cb_baton);
quic_conn_mark_used(qconn, demux->conn_table);
- kr_quic_table_sweep(demux->conn_table, ctx);
+ // kr_quic_table_sweep(demux->conn_table, ctx);
return protolayer_break(ctx, kr_ok());
}
{
struct pl_quic_demux_sess_data *quic = data;
kr_quic_table_free(quic->conn_table);
-
return kr_ok();
}
return PROTOLAYER_EVENT_CONSUME;
}
- if (event == PROTOLAYER_EVENT_DISCONNECT) {
+ if (event == PROTOLAYER_EVENT_DISCONNECT ||
+ event == PROTOLAYER_EVENT_CONNECT_TIMEOUT) {
if (*baton == NULL)
return PROTOLAYER_EVENT_CONSUME;