+static void release_all_events_cb(void*closure, uint16_t id, void *ptr)
+{
+ struct afb_event_x2 *eventid = ptr;
+ afb_evt_event_x2_unref(eventid);
+}
+
+/* disconnect */
+static void disconnect(struct afb_stub_ws *stubws)
+{
+ struct u16id2ptr *i2p;
+ struct u16id2bool *i2b;
+
+ afb_proto_ws_unref(__atomic_exchange_n(&stubws->proto, NULL, __ATOMIC_RELAXED));
+ if (stubws->is_client) {
+ i2p = __atomic_exchange_n(&stubws->event_proxies, NULL, __ATOMIC_RELAXED);
+ if (i2p) {
+ u16id2ptr_forall(i2p, release_all_events_cb, NULL);
+ u16id2ptr_destroy(&i2p);
+ }
+ i2b = __atomic_exchange_n(&stubws->session_flags, NULL, __ATOMIC_RELAXED);
+ u16id2bool_destroy(&i2b);
+ i2b = __atomic_exchange_n(&stubws->token_flags, NULL, __ATOMIC_RELAXED);
+ u16id2bool_destroy(&i2b);
+ } else {
+ afb_evt_listener_unref(__atomic_exchange_n(&stubws->listener, NULL, __ATOMIC_RELAXED));
+ afb_cred_unref(__atomic_exchange_n(&stubws->cred, NULL, __ATOMIC_RELAXED));
+ i2b = __atomic_exchange_n(&stubws->event_flags, NULL, __ATOMIC_RELAXED);
+ u16id2bool_destroy(&i2b);
+ i2p = __atomic_exchange_n(&stubws->session_proxies, NULL, __ATOMIC_RELAXED);
+ if (i2p) {
+ u16id2ptr_forall(i2p, release_all_sessions_cb, NULL);
+ u16id2ptr_destroy(&i2p);
+ }
+ i2p = __atomic_exchange_n(&stubws->token_proxies, NULL, __ATOMIC_RELAXED);
+ if (i2p) {
+ u16id2ptr_forall(i2p, release_all_tokens_cb, NULL);
+ u16id2ptr_destroy(&i2p);
+ }