+ app_ns = app_namespace_get (handle->aah_app_ns_index);
+ cs = appns_sapi_get_socket (app_ns, handle->aah_sock_index);
+ if (!cs)
+ return 0;
+
+ sapi_socket_detach (app_ns, cs);
+ return 0;
+}
+
+static clib_error_t *
+sapi_sock_accept_ready (clib_file_t * scf)
+{
+ app_ns_api_handle_t handle = *(app_ns_api_handle_t *) & scf->private_data;
+ app_namespace_t *app_ns;
+ clib_file_t cf = { 0 };
+ clib_error_t *err = 0;
+ clib_socket_t *ccs, *scs;
+
+ /* Listener files point to namespace */
+ app_ns = app_namespace_get (handle.aah_app_ns_index);
+
+ /*
+ * Initialize client socket
+ */
+ ccs = appns_sapi_alloc_socket (app_ns);
+
+ /* Grab server socket after client is initialized */
+ scs = appns_sapi_get_socket (app_ns, handle.aah_sock_index);
+ if (!scs)
+ goto error;
+
+ err = clib_socket_accept (scs, ccs);
+ if (err)
+ {
+ clib_error_report (err);
+ goto error;
+ }
+
+ cf.read_function = sapi_sock_read_ready;
+ cf.write_function = sapi_sock_write_ready;
+ cf.error_function = sapi_sock_error;
+ cf.file_descriptor = ccs->fd;
+ /* File points to app namespace and socket */
+ handle.aah_sock_index = appns_sapi_socket_index (app_ns, ccs);
+ cf.private_data = handle.as_u64;
+ cf.description = format (0, "app sock conn fd: %d", ccs->fd);
+
+ /* Poll until we get an attach message. Socket points to file and
+ * application that owns the socket */
+ handle.aah_app_wrk_index = APP_INVALID_INDEX;
+ handle.aah_file_index = clib_file_add (&file_main, &cf);
+ ccs->private_data = handle.as_u64;
+
+ return err;
+
+error:
+ appns_sapi_free_socket (app_ns, ccs);
+ return err;
+}
+
+void
+appns_sapi_del_ns_socket (app_namespace_t *app_ns)
+{
+ app_ns_api_handle_t *handle;
+ clib_socket_t *cs;
+
+ pool_foreach (cs, app_ns->app_sockets)
+ {
+ handle = (app_ns_api_handle_t *) &cs->private_data;
+ clib_file_del_by_index (&file_main, handle->aah_file_index);
+
+ clib_socket_close (cs);
+ clib_socket_free (cs);
+ }
+ pool_free (app_ns->app_sockets);
+}
+
+int
+appns_sapi_add_ns_socket (app_namespace_t * app_ns)
+{
+ char *subdir = "/app_ns_sockets/";
+ app_ns_api_handle_t *handle;
+ clib_file_t cf = { 0 };
+ struct stat file_stat;
+ clib_error_t *err;
+ clib_socket_t *cs;
+ char dir[4096];
+
+ if (app_ns->netns)
+ {
+ if (!app_ns->sock_name)
+ app_ns->sock_name = format (0, "@vpp/session/%v%c", app_ns->ns_id, 0);
+ if (app_ns->sock_name[0] != '@')
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+ else
+ {
+ snprintf (dir, sizeof (dir), "%s%s", vlib_unix_get_runtime_dir (),
+ subdir);
+ err = vlib_unix_recursive_mkdir ((char *) dir);
+ if (err)
+ {
+ clib_error_report (err);
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
+ }
+
+ if (!app_ns->sock_name)
+ app_ns->sock_name = format (0, "%s%v%c", dir, app_ns->ns_id, 0);
+ }
+
+ /*
+ * Create and initialize socket to listen on
+ */
+ cs = appns_sapi_alloc_socket (app_ns);
+ cs->config = (char *) vec_dup (app_ns->sock_name);
+ cs->flags = CLIB_SOCKET_F_IS_SERVER |
+ CLIB_SOCKET_F_ALLOW_GROUP_WRITE |
+ CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED;
+
+ if ((err = clib_socket_init_netns (cs, app_ns->netns)))
+ {
+ clib_error_report (err);
+ return -1;
+ }
+
+ if (!app_ns->netns && stat ((char *) app_ns->sock_name, &file_stat) == -1)
+ return -1;
+
+ /*
+ * Start polling it
+ */
+ cf.read_function = sapi_sock_accept_ready;
+ cf.file_descriptor = cs->fd;
+ /* File points to namespace */
+ handle = (app_ns_api_handle_t *) & cf.private_data;
+ handle->aah_app_ns_index = app_namespace_index (app_ns);
+ handle->aah_sock_index = appns_sapi_socket_index (app_ns, cs);
+ cf.description = format (0, "app sock listener: %s", app_ns->sock_name);
+
+ /* Socket points to clib file index */
+ handle = (app_ns_api_handle_t *) & cs->private_data;
+ handle->aah_file_index = clib_file_add (&file_main, &cf);
+ handle->aah_app_wrk_index = APP_INVALID_INDEX;
+
+ return 0;
+}
+
+#include <vnet/session/session.api.c>
+static clib_error_t *
+session_api_hookup (vlib_main_t *vm)
+{