open = req->open_req_list;
while(open) {
nopen = open->next;
- mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp);
+ mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp,
+ NULL);
free(open);
open = nopen;
}
return conn;
}
+/** The arguments for doq stream tree del. */
+struct doq_stream_tree_del_args {
+ /** The doq table. */
+ struct doq_table* table;
+ /** The doq connection for the stream. */
+ struct doq_conn* conn;
+};
+
/** delete stream tree node */
static void
stream_tree_del(rbnode_type* node, void* arg)
{
- struct doq_table* table = (struct doq_table*)arg;
+ struct doq_stream_tree_del_args* args = (struct doq_stream_tree_del_args*)arg;
+ struct doq_table* table = args->table;
struct doq_stream* stream;
if(!node)
return;
stream = (struct doq_stream*)node;
+ if(stream->mesh_state) {
+ mesh_state_remove_reply(stream->mesh, stream->mesh_state,
+ args->conn->doq_socket->cp, stream);
+ stream->mesh_state = NULL;
+ }
if(stream->in)
doq_table_quic_size_subtract(table, stream->inlen);
if(stream->out)
* because the ngtcp2 conn is deleted. */
SSL_set_app_data(conn->ssl, NULL);
if(conn->stream_tree.count != 0) {
- traverse_postorder(&conn->stream_tree, stream_tree_del, table);
+ struct doq_stream_tree_del_args args;
+ memset(&args, 0, sizeof(args));
+ args.table = table;
+ args.conn = conn;
+ traverse_postorder(&conn->stream_tree, stream_tree_del, &args);
}
free(conn->key.dcid);
SSL_free(conn->ssl);
if(stream->is_closed)
return 1;
stream->is_closed = 1;
+ if(stream->mesh_state) {
+ mesh_state_remove_reply(stream->mesh, stream->mesh_state,
+ conn->doq_socket->cp, stream);
+ stream->mesh_state = NULL;
+ }
doq_stream_off_write_list(conn, stream);
if(send_shutdown) {
verbose(VERB_ALGO, "doq: shutdown stream_id %d with app_error_code %d",
doq_conn_write_enable(conn);
return 1;
}
+#endif /* HAVE_NGTCP2 */
+void
+doq_stream_add_meshstate(struct doq_stream* stream,
+ struct mesh_area* mesh, struct mesh_state* m)
+{
+#ifdef HAVE_NGTCP2
+ stream->mesh = mesh;
+ stream->mesh_state = m;
+#else
+ (void)stream; (void)mesh; (void)m;
+#endif
+}
+
+void
+doq_stream_remove_mesh_state(struct doq_stream* stream)
+{
+#ifdef HAVE_NGTCP2
+ if(!stream)
+ return;
+ stream->mesh_state = NULL;
+#else
+ (void)stream;
+#endif
+}
+
+#ifdef HAVE_NGTCP2
/** doq stream data length has completed, allocations can be done. False on
* allocation failure. */
static int
return 0;
}
c->repinfo.doq_streamid = stream->stream_id;
+ c->repinfo.doq_stream = stream;
conn->doq_socket->current_conn = conn;
fptr_ok(fptr_whitelist_comm_point(c->callback));
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo)) {
struct addrinfo;
struct sldns_buffer;
struct tcl_list;
+struct mesh_area;
+struct mesh_state;
/**
* Listening for queries structure.
uint8_t* out;
/** if the stream is on the write list */
uint8_t on_write_list;
+ /** The mesh area and mesh state, set when this stream's query was
+ * dispatched into the mesh; used to detach the reply on stream close */
+ struct mesh_area* mesh;
+ /** the mesh state for the query, is nonNULL when there is one. */
+ struct mesh_state* mesh_state;
/** the prev and next on the write list, if on the list */
struct doq_stream* write_prev, *write_next;
};
/** send reply for a connection */
int doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
struct sldns_buffer* buf);
+#endif /* HAVE_NGTCP2 */
+/** add mesh state to doq stream */
+void doq_stream_add_meshstate(struct doq_stream* stream,
+ struct mesh_area* mesh, struct mesh_state* m);
+
+/** remove mesh state from doq stream */
+void doq_stream_remove_mesh_state(struct doq_stream* stream);
+
+#ifdef HAVE_NGTCP2
/** the connection has write interest, wants to write packets */
void doq_conn_write_enable(struct doq_conn* conn);
"incoming query.");
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
+ else if(rep->c->type == comm_doq && rep->doq_stream)
+ doq_stream_remove_mesh_state(rep->doq_stream);
comm_point_drop_reply(rep);
mesh->stats_dropped++;
return;
"dropping incoming query.");
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
+ else if(rep->c->type == comm_doq && rep->doq_stream)
+ doq_stream_remove_mesh_state(rep->doq_stream);
comm_point_drop_reply(rep);
mesh->num_queries_replyaddr_limit++;
return;
}
if(rep->c->use_h2) {
http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
+ } else if(rep->c->type == comm_doq && rep->doq_stream) {
+ doq_stream_add_meshstate(rep->doq_stream, mesh, s);
}
/* add serve expired timer if required and not already there */
if(timeout && !mesh_serve_expired_init(s, timeout)) {
qinfo, qid, qflags, edns);
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
+ else if(rep->c->type == comm_doq && rep->doq_stream)
+ doq_stream_remove_mesh_state(rep->doq_stream);
comm_point_send_reply(rep);
if(added)
mesh_state_delete(&s->s);
* for HTTP/2 stream to refer to mesh state, in case
* connection gets cleanup before HTTP/2 stream close. */
r->h2_stream->mesh_state = NULL;
+#ifdef HAVE_NGTCP2
+ } else if(r->query_reply.doq_stream) {
+ r->query_reply.doq_stream->mesh_state = NULL;
+#endif
}
/* send the reply */
/* We don't reuse the encoded answer if:
mstate->reply_list = NULL;
if(r->query_reply.c->use_h2)
http2_stream_remove_mesh_state(r->h2_stream);
+ else if(r->query_reply.doq_stream)
+ doq_stream_remove_mesh_state(r->query_reply.doq_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
mstate->reply_list = NULL;
if(r->query_reply.c->use_h2) {
http2_stream_remove_mesh_state(r->h2_stream);
+ } else if(r->query_reply.doq_stream) {
+ doq_stream_remove_mesh_state(r->query_reply.doq_stream);
}
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
if(rep->c->use_h2)
r->h2_stream = rep->c->h2_stream;
else r->h2_stream = NULL;
+ if(rep->c->type != comm_doq)
+ r->query_reply.doq_stream = NULL;
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
* and can be different for different original queries (even if the
}
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
- struct comm_point* cp)
+ struct comm_point* cp, struct doq_stream* doq_stream)
{
struct mesh_reply* n, *prev = NULL;
n = m->reply_list;
* there is no accounting twice */
if(!n) return; /* nothing to remove, also no accounting needed */
while(n) {
- if(n->query_reply.c == cp) {
+ if(n->query_reply.c == cp
+ && (!doq_stream || n->query_reply.doq_stream == doq_stream)) {
/* unlink it */
if(prev) prev->next = n->next;
else m->reply_list = n->next;
* share the same comm_point); make sure the streams
* don't point back. */
if(n->h2_stream) n->h2_stream->mesh_state = NULL;
+#ifdef HAVE_NGTCP2
+ if(n->query_reply.doq_stream)
+ n->query_reply.doq_stream->mesh_state = NULL;
+#endif
/* prev = prev; */
n = n->next;
mstate->reply_list = NULL;
if(r->query_reply.c->use_h2)
http2_stream_remove_mesh_state(r->h2_stream);
+ else if(r->query_reply.doq_stream)
+ doq_stream_remove_mesh_state(r->query_reply.doq_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->num_queries_discard_timeout++;
* @param mesh: to update the counters.
* @param m: the mesh state.
* @param cp: the comm_point to remove from the list.
+ * @param doq_stream: if not NULL, it specifies the doq_stream to match
+ * for the delete.
*/
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
- struct comm_point* cp);
+ struct comm_point* cp, struct doq_stream* doq_stream);
/** Callback for when the serve expired client timer has run out. Tries to
* find an expired answer in the cache and reply that to the client.
{
}
+void doq_stream_add_meshstate(struct doq_stream* ATTR_UNUSED(stream),
+ struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m))
+{
+}
+
+void doq_stream_remove_mesh_state(struct doq_stream* ATTR_UNUSED(stream))
+{
+}
+
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
void* ATTR_UNUSED(arg))
{
{
if(h2_stream->mesh_state) {
mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state,
- h2_session->c);
+ h2_session->c, NULL);
h2_stream->mesh_state = NULL;
}
http2_req_stream_clear(h2_stream);
/** port number for doq */
int doq_srcport;
#endif /* HAVE_NGTCP2 */
+ /** The doq stream to register mesh states to. */
+ struct doq_stream* doq_stream;
};
/**