+static void
+session_mq_accepted_reply_handler (void *data)
+{
+ session_accepted_reply_msg_t *mp = (session_accepted_reply_msg_t *) data;
+ vnet_disconnect_args_t _a = { 0 }, *a = &_a;
+ app_worker_t *app_wrk;
+ local_session_t *ls;
+ stream_session_t *s;
+
+ /* Server isn't interested, kill the session */
+ if (mp->retval)
+ {
+ a->app_index = mp->context;
+ a->handle = mp->handle;
+ vnet_disconnect_session (a);
+ return;
+ }
+
+ if (session_handle_is_local (mp->handle))
+ {
+ ls = application_get_local_session_from_handle (mp->handle);
+ if (!ls)
+ {
+ clib_warning ("unknown local handle 0x%lx", mp->handle);
+ return;
+ }
+ app_wrk = app_worker_get (ls->app_wrk_index);
+ if (app_wrk->app_index != mp->context)
+ {
+ clib_warning ("server %u doesn't own local handle 0x%lx",
+ mp->context, mp->handle);
+ return;
+ }
+ if (application_local_session_connect_notify (ls))
+ return;
+ ls->session_state = SESSION_STATE_READY;
+ }
+ else
+ {
+ s = session_get_from_handle_if_valid (mp->handle);
+ if (!s)
+ {
+ clib_warning ("session doesn't exist");
+ return;
+ }
+ app_wrk = app_worker_get (s->app_wrk_index);
+ if (app_wrk->app_index != mp->context)
+ {
+ clib_warning ("app doesn't own session");
+ return;
+ }
+ s->session_state = SESSION_STATE_READY;
+ if (!svm_fifo_is_empty (s->server_rx_fifo))
+ app_worker_lock_and_send_event (app_wrk, s, FIFO_EVENT_APP_RX);
+ }
+}
+
+static void
+session_mq_reset_reply_handler (void *data)
+{
+ session_reset_reply_msg_t *mp;
+ app_worker_t *app_wrk;
+ stream_session_t *s;
+ application_t *app;
+ u32 index, thread_index;
+
+ mp = (session_reset_reply_msg_t *) data;
+ app = application_lookup (mp->client_index);
+ if (!app)
+ return;
+
+ session_parse_handle (mp->handle, &index, &thread_index);
+ s = session_get_if_valid (index, thread_index);
+ if (!s)
+ {
+ clib_warning ("Invalid session!");
+ return;
+ }
+ app_wrk = app_worker_get (s->app_wrk_index);
+ if (!app_wrk || app_wrk->app_index != app->app_index)
+ {
+ clib_warning ("App % does not own handle 0x%lx!", app->app_index,
+ mp->handle);
+ return;
+ }
+
+ /* Client objected to resetting the session, log and continue */
+ if (mp->retval)
+ {
+ clib_warning ("client retval %d", mp->retval);
+ return;
+ }
+
+ /* This comes as a response to a reset, transport only waiting for
+ * confirmation to remove connection state, no need to disconnect */
+ stream_session_cleanup (s);
+}
+
+static void
+session_mq_disconnected_handler (void *data)
+{
+ session_disconnected_reply_msg_t *rmp;
+ vnet_disconnect_args_t _a, *a = &_a;
+ svm_msg_q_msg_t _msg, *msg = &_msg;
+ session_disconnected_msg_t *mp;
+ app_worker_t *app_wrk;
+ session_event_t *evt;
+ stream_session_t *s;
+ application_t *app;
+ int rv = 0;
+
+ mp = (session_disconnected_msg_t *) data;
+ if (!(s = session_get_from_handle_if_valid (mp->handle)))
+ {
+ clib_warning ("could not disconnect handle %llu", mp->handle);
+ return;
+ }
+ app_wrk = app_worker_get (s->app_wrk_index);
+ app = application_lookup (mp->client_index);
+ if (!(app_wrk && app && app->app_index == app_wrk->app_index))
+ {
+ clib_warning ("could not disconnect session: %llu app: %u",
+ mp->handle, mp->client_index);
+ return;
+ }
+
+ a->handle = mp->handle;
+ a->app_index = app_wrk->wrk_index;
+ rv = vnet_disconnect_session (a);
+
+ svm_msg_q_lock_and_alloc_msg_w_ring (app_wrk->event_queue,
+ SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, msg);
+ svm_msg_q_unlock (app_wrk->event_queue);
+ evt = svm_msg_q_msg_data (app_wrk->event_queue, msg);
+ memset (evt, 0, sizeof (*evt));
+ evt->event_type = SESSION_CTRL_EVT_DISCONNECTED;
+ rmp = (session_disconnected_reply_msg_t *) evt->data;
+ rmp->handle = mp->handle;
+ rmp->context = mp->context;
+ rmp->retval = rv;
+ svm_msg_q_add (app_wrk->event_queue, msg, SVM_Q_WAIT);
+}
+
+static void
+session_mq_disconnected_reply_handler (void *data)
+{
+ session_disconnected_reply_msg_t *mp;
+ vnet_disconnect_args_t _a, *a = &_a;
+ application_t *app;
+
+ mp = (session_disconnected_reply_msg_t *) data;
+
+ /* Client objected to disconnecting the session, log and continue */
+ if (mp->retval)
+ {
+ clib_warning ("client retval %d", mp->retval);
+ return;
+ }
+
+ /* Disconnect has been confirmed. Confirm close to transport */
+ app = application_lookup (mp->context);
+ if (app)
+ {
+ a->handle = mp->handle;
+ a->app_index = app->app_index;
+ vnet_disconnect_session (a);
+ }
+}
+