allow abstract unix sockets
[src/app-framework-binder.git] / src / afb-api-ws.c
index ea0781d..ba9a18a 100644 (file)
@@ -42,7 +42,8 @@
 #include "afb-cred.h"
 #include "afb-ws.h"
 #include "afb-msg-json.h"
-#include "afb-apis.h"
+#include "afb-api.h"
+#include "afb-apiset.h"
 #include "afb-api-so.h"
 #include "afb-context.h"
 #include "afb-evt.h"
@@ -76,13 +77,13 @@ struct api_ws
        pthread_mutex_t mutex;  /**< resource control */
        union {
                struct {
-                       uint32_t id;
                        struct afb_ws *ws;
                        struct api_ws_event *events;
                        struct api_ws_memo *memos;
                } client;
                struct {
                        sd_event_source *listensrc; /**< systemd source for server socket */
+                       struct afb_apiset *apiset;
                } server;
        };
 };
@@ -91,6 +92,18 @@ struct api_ws
 #define RETERR  2
 #define RETRAW  3
 
+/******************* common usefull tools **********************************/
+
+/**
+ * translate a pointer to some integer
+ * @param ptr the pointer to translate
+ * @return an integer
+ */
+static inline uint32_t ptr2id(void *ptr)
+{
+       return (uint32_t)(((intptr_t)ptr) >> 6);
+}
+
 /******************* websocket interface for client part **********************************/
 
 static void api_ws_client_on_binary(void *closure, char *data, size_t size);
@@ -169,6 +182,9 @@ struct api_ws_client
 
        /* pending subcalls */
        struct api_ws_subcall *subcalls;
+
+       /* apiset */
+       struct afb_apiset *apiset;
 };
 
 /******************* websocket interface for client part **********************************/
@@ -238,7 +254,7 @@ static struct api_ws *api_ws_make(const char *path)
        while (length && path[length - 1] != '/' && path[length - 1] != ':')
                length = length - 1;
        api->api = &api->path[length];
-       if (api->api == NULL || !afb_apis_is_valid_api_name(api->api)) {
+       if (api->api == NULL || !afb_api_is_valid_name(api->api)) {
                errno = EINVAL;
                goto error2;
        }
@@ -265,7 +281,7 @@ static int api_ws_socket_unix(const char *path, int server)
                return -1;
        }
 
-       if (server)
+       if (server && path[0] != '@')
                unlink(path);
 
        fd = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -275,6 +291,8 @@ static int api_ws_socket_unix(const char *path, int server)
        memset(&addr, 0, sizeof addr);
        addr.sun_family = AF_UNIX;
        strcpy(addr.sun_path, path);
+       if (addr.sun_path[0] == '@')
+               addr.sun_path[0] = 0; /* implement abstract sockets */
        if (server) {
                rc = bind(fd, (struct sockaddr *) &addr, (socklen_t)(sizeof addr));
        } else {
@@ -540,7 +558,9 @@ static struct api_ws_memo *api_ws_client_memo_make(struct api_ws *api, struct af
        if (memo != NULL) {
                afb_xreq_addref(xreq);
                memo->xreq = xreq;
-               do { memo->msgid = ++api->client.id; } while(api_ws_client_memo_search(api, memo->msgid) != NULL);
+               memo->msgid = ptr2id(memo);
+               while(api_ws_client_memo_search(api, memo->msgid) != NULL)
+                       memo->msgid++;
                memo->api = api;
                memo->next = api->client.memos;
                api->client.memos = memo;
@@ -931,19 +951,6 @@ end:
        pthread_mutex_unlock(&apiws->mutex);
 }
 
-static int api_ws_service_start_cb(void *closure, int share_session, int onneed)
-{
-       struct api_ws *api = closure;
-
-       /* not an error when onneed */
-       if (onneed != 0)
-               return 0;
-
-       /* already started: it is an error */
-       ERROR("The WS binding %s is not a startable service", api->path);
-       return -1;
-}
-
 /*  */
 static void api_ws_client_disconnect(struct api_ws *api)
 {
@@ -975,12 +982,11 @@ static int api_ws_client_connect(struct api_ws *api)
 }
 
 static struct afb_api_itf ws_api_itf = {
-       .call = api_ws_client_call_cb,
-       .service_start = api_ws_service_start_cb
+       .call = api_ws_client_call_cb
 };
 
 /* adds a afb-ws-service client api */
-int afb_api_ws_add_client(const char *path)
+int afb_api_ws_add_client(const char *path, struct afb_apiset *apiset)
 {
        int rc;
        struct api_ws *api;
@@ -1001,7 +1007,7 @@ int afb_api_ws_add_client(const char *path)
        /* record it as an API */
        afb_api.closure = api;
        afb_api.itf = &ws_api_itf;
-       if (afb_apis_add(api->api, afb_api) < 0)
+       if (afb_apiset_add(apiset, api->api, afb_api) < 0)
                goto error3;
 
        return 0;
@@ -1031,6 +1037,7 @@ static void api_ws_server_client_unref(struct api_ws_client *client)
                        free(sc);
                }
                afb_cred_unref(client->cred);
+               afb_apiset_unref(client->apiset);
                free(client);
        }
 }
@@ -1081,8 +1088,7 @@ static void api_ws_server_on_call(struct api_ws_client *client, struct readbuf *
        wreq->xreq.api = client->api;
        wreq->xreq.verb = cverb;
        wreq->xreq.json = object;
-       afb_apis_call(&wreq->xreq);
-       afb_xreq_unref(&wreq->xreq);
+       afb_xreq_process(&wreq->xreq, client->apiset);
        return;
 
 unconnected:
@@ -1180,6 +1186,7 @@ static void api_ws_server_accept(struct api_ws *api)
                                client->ws = afb_ws_create(afb_common_get_event_loop(), client->fd, &api_ws_server_ws_itf, client);
                                if (client->ws != NULL) {
                                        client->api = api->api;
+                                       client->apiset = afb_apiset_addref(api->server.apiset);
                                        client->refcount = 1;
                                        client->subcalls = NULL;
                                        return;
@@ -1312,7 +1319,7 @@ static void api_ws_server_req_subcall_cb(struct afb_xreq *xreq, const char *api,
                sc->closure = cb_closure;
 
                pthread_mutex_unlock(&client->mutex);
-               sc->subcallid = (uint32_t)(((intptr_t)sc) >> 6);
+               sc->subcallid = ptr2id(sc);
                do {
                        sc->subcallid++;
                        osc = client->subcalls;
@@ -1429,7 +1436,7 @@ static int api_ws_server_connect(struct api_ws *api)
 }
 
 /* create the service */
-int afb_api_ws_add_server(const char *path)
+int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset)
 {
        int rc;
        struct api_ws *api;
@@ -1444,6 +1451,7 @@ int afb_api_ws_add_server(const char *path)
        if (rc < 0)
                goto error2;
 
+       api->server.apiset = afb_apiset_addref(apiset);
        return 0;
 
 error2: