: NULL;
}
+struct session2 *session2_get_root(struct session2 *s)
+{
+ while (s && s->transport.type == SESSION2_TRANSPORT_PARENT)
+ s = s->transport.parent;
+
+ return (s && s->transport.type == SESSION2_TRANSPORT_IO)
+ ? s
+ : NULL;
+}
+
static void session2_on_timeout(uv_timer_t *timer)
{
struct session2 *s = timer->data;
bool is_close_event = (event == PROTOLAYER_EVENT_CLOSE ||
event == PROTOLAYER_EVENT_FORCE_CLOSE);
if (is_close_event) {
- session2_waitinglist_finalize(s, KR_STATE_FAIL);
- session2_tasklist_finalize(s, KR_STATE_FAIL);
session2_timer_stop(s);
s->closing = true;
}
return kr_ok();
case SESSION2_TRANSPORT_PARENT:;
- session2_event_wrap(s, event, baton);
+ /* Pass the event along to the parent session. So far only DoQ uses
+ * subsessions. These events are used to remove references
+ * to terminating sessions in the parent session. */
+ if (kr_fails_assert(s->transport.parent)) {
+ return kr_error(EINVAL);
+ }
+ session2_event_wrap(s->transport.parent, event, baton);
return kr_ok();
default:
* May return `NULL` if no peer is set. */
KR_EXPORT uv_handle_t *session2_get_handle(struct session2 *s);
+/** Gets the io session from the specified session, iterating through the
+ * session hierarchy (child-to-parent) until an `_IO` session is found if
+ * needed.
+ *
+ * May return `NULL` if no peer is set. */
+KR_EXPORT struct session2 *session2_get_root(struct session2 *s);
+
/** Start the session timer. On timeout, the specified `event` is sent in the
* `_UNWRAP` direction. Only a single timeout can be active at a time. */
int session2_timer_start(struct session2 *s, enum protolayer_event_type event,