+int
+session_open_cl (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
+{
+ transport_connection_t *tc;
+ transport_endpoint_cfg_t *tep;
+ segment_manager_t *sm;
+ app_worker_t *app_wrk;
+ stream_session_t *s;
+ application_t *app;
+ int rv;
+
+ tep = session_endpoint_to_transport_cfg (rmt);
+ rv = tp_vfts[rmt->transport_proto].open (tep);
+ if (rv < 0)
+ {
+ SESSION_DBG ("Transport failed to open connection.");
+ return VNET_API_ERROR_SESSION_CONNECT;
+ }
+
+ tc = tp_vfts[rmt->transport_proto].get_half_open ((u32) rv);
+
+ /* For dgram type of service, allocate session and fifos now.
+ */
+ app_wrk = app_worker_get (app_wrk_index);
+ sm = app_worker_get_connect_segment_manager (app_wrk);
+
+ if (session_alloc_and_init (sm, tc, 1, &s))
+ return -1;
+ s->app_wrk_index = app_wrk->wrk_index;
+ s->session_state = SESSION_STATE_OPENED;
+
+ /* Tell the app about the new event fifo for this session */
+ app = application_get (app_wrk->app_index);
+ app->cb_fns.session_connected_callback (app_wrk->wrk_index, opaque, s, 0);
+
+ return 0;
+}
+
+int
+session_open_vc (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
+{
+ transport_connection_t *tc;
+ transport_endpoint_cfg_t *tep;
+ u64 handle;
+ int rv;
+
+ tep = session_endpoint_to_transport_cfg (rmt);
+ rv = tp_vfts[rmt->transport_proto].open (tep);
+ if (rv < 0)
+ {
+ SESSION_DBG ("Transport failed to open connection.");
+ return VNET_API_ERROR_SESSION_CONNECT;
+ }
+
+ tc = tp_vfts[rmt->transport_proto].get_half_open ((u32) rv);
+
+ /* If transport offers a stream service, only allocate session once the
+ * connection has been established.
+ * Add connection to half-open table and save app and tc index. The
+ * latter is needed to help establish the connection while the former
+ * is needed when the connect notify comes and we have to notify the
+ * external app
+ */
+ handle = (((u64) app_wrk_index) << 32) | (u64) tc->c_index;
+ session_lookup_add_half_open (tc, handle);
+
+ /* Store api_context (opaque) for when the reply comes. Not the nicest
+ * thing but better than allocating a separate half-open pool.
+ */
+ tc->s_index = opaque;
+ return 0;
+}
+
+int
+session_open_app (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
+{
+ session_endpoint_cfg_t *sep = (session_endpoint_cfg_t *) rmt;
+ transport_endpoint_cfg_t *tep_cfg = session_endpoint_to_transport_cfg (sep);
+
+ sep->app_wrk_index = app_wrk_index;
+ sep->opaque = opaque;
+
+ return tp_vfts[rmt->transport_proto].open (tep_cfg);
+}
+
+typedef int (*session_open_service_fn) (u32, session_endpoint_t *, u32);
+
+/* *INDENT-OFF* */
+static session_open_service_fn session_open_srv_fns[TRANSPORT_N_SERVICES] = {
+ session_open_vc,
+ session_open_cl,
+ session_open_app,
+};
+/* *INDENT-ON* */
+
+/**
+ * Ask transport to open connection to remote transport endpoint.
+ *
+ * Stores handle for matching request with reply since the call can be
+ * asynchronous. For instance, for TCP the 3-way handshake must complete
+ * before reply comes. Session is only created once connection is established.
+ *
+ * @param app_index Index of the application requesting the connect
+ * @param st Session type requested.
+ * @param tep Remote transport endpoint
+ * @param opaque Opaque data (typically, api_context) the application expects
+ * on open completion.
+ */
+int
+session_open (u32 app_wrk_index, session_endpoint_t * rmt, u32 opaque)
+{
+ transport_service_type_t tst = tp_vfts[rmt->transport_proto].service_type;
+ return session_open_srv_fns[tst] (app_wrk_index, rmt, opaque);
+}
+
+/**
+ * Ask transport to listen on session endpoint.
+ *
+ * @param s Session for which listen will be called. Note that unlike
+ * established sessions, listen sessions are not associated to a
+ * thread.
+ * @param sep Local endpoint to be listened on.
+ */
+int
+session_listen (stream_session_t * ls, session_endpoint_cfg_t * sep)