afb-api-ws: Use afb-socket features 43/16243/1
authorJose Bollo <jose.bollo@iot.bzh>
Mon, 20 Aug 2018 14:53:27 +0000 (16:53 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Wed, 22 Aug 2018 12:03:52 +0000 (14:03 +0200)
Use the feature of afb-socket to handle
the api name.

Bug-AGL: SPEC-1668

Change-Id: Ib13891d7948c75bc5d342b45c774f8e6c3ea016e
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
src/afb-api-ws.c

index 611f887..6d8506c 100644 (file)
 #include "verbose.h"
 #include "fdev.h"
 
-struct api_ws
+struct api_ws_server
 {
-       char *uri;              /* uri of the object for the API */
-       char *api;              /* api name of the interface */
-       struct fdev *fdev;      /* fdev handler */
-       struct afb_apiset *apiset;
+       struct afb_apiset *apiset;      /* the apiset for calling */
+       struct fdev *fdev;              /* fdev handler */
+       uint16_t offapi;                /* api name of the interface */
+       char uri[1];                    /* the uri of the server socket */
 };
 
 /******************************************************************************/
-
-/*
- * create a structure api_ws not connected to the 'uri'.
- */
-static struct api_ws *api_ws_make(const char *uri)
-{
-       struct api_ws *api;
-       size_t length;
-
-       /* allocates the structure */
-       length = strlen(uri);
-       api = calloc(1, sizeof *api + 1 + length);
-       if (api == NULL) {
-               errno = ENOMEM;
-               goto error;
-       }
-
-       /* uri is copied after the struct */
-       api->uri = (char*)(api+1);
-       memcpy(api->uri, uri, length + 1);
-
-       /* api name is at the end of the uri */
-       while (length && uri[length - 1] != '/' && uri[length - 1] != ':')
-               length = length - 1;
-       api->api = &api->uri[length];
-       if (api->api == NULL || !afb_api_is_valid_name(api->api)) {
-               errno = EINVAL;
-               goto error2;
-       }
-
-       return api;
-
-error2:
-       free(api);
-error:
-       return NULL;
-}
-
-/**********************************************************************************/
+/***       C L I E N T                                                      ***/
+/******************************************************************************/
 
 int afb_api_ws_add_client(const char *uri, struct afb_apiset *declare_set, struct afb_apiset *call_set, int strong)
 {
-       struct api_ws *apiws;
        struct afb_stub_ws *stubws;
+       struct fdev *fdev;
+       const char *api;
 
-       /* create the ws client api */
-       apiws = api_ws_make(uri);
-       if (apiws == NULL)
+       /* check the api name */
+       api = afb_socket_api(uri);
+       if (api == NULL || !afb_api_is_valid_name(api)) {
+               ERROR("invalid (too long) ws client uri %s", uri);
+               errno = EINVAL;
                goto error;
-
-       /* connect to the service */
-       apiws->fdev = afb_socket_open_fdev(apiws->uri, 0);
-       if (!apiws->fdev)
-               goto error2;
-
-       stubws = afb_stub_ws_create_client(apiws->fdev, apiws->api, call_set);
-       if (!stubws) {
-               ERROR("can't setup client ws service to %s", apiws->uri);
-               goto error3;
        }
-       if (afb_stub_ws_client_add(stubws, declare_set) < 0) {
-               ERROR("can't add the client to the apiset for service %s", apiws->uri);
-               goto error3;
+
+       /* open the socket */
+       fdev = afb_socket_open_fdev(uri, 0);
+       if (fdev) {
+               /* create the client stub */
+               stubws = afb_stub_ws_create_client(fdev, api, call_set);
+               if (!stubws) {
+                       ERROR("can't setup client ws service to %s", uri);
+                       fdev_unref(fdev);
+               } else {
+                       if (afb_stub_ws_client_add(stubws, declare_set) >= 0)
+                               return 0;
+                       ERROR("can't add the client to the apiset for service %s", uri);
+                       afb_stub_ws_unref(stubws);
+               }
        }
-       free(apiws);
-       return 0;
-error3:
-       afb_stub_ws_unref(stubws);
-error2:
-       free(apiws);
 error:
        return -!!strong;
 }
@@ -131,17 +93,17 @@ int afb_api_ws_add_client_weak(const char *uri, struct afb_apiset *declare_set,
        return afb_api_ws_add_client(uri, declare_set, call_set, 0);
 }
 
-static int api_ws_server_accept_client(struct api_ws *apiws, struct fdev *fdev)
-{
-       return -!afb_stub_ws_create_server(fdev, apiws->api, apiws->apiset);
-}
+/*****************************************************************************/
+/***       S E R V E R                                                      ***/
+/******************************************************************************/
 
-static void api_ws_server_accept(struct api_ws *apiws)
+static void api_ws_server_accept(struct api_ws_server *apiws)
 {
-       int rc, fd;
+       int fd;
        struct sockaddr addr;
        socklen_t lenaddr;
        struct fdev *fdev;
+       struct afb_stub_ws *server;
 
        lenaddr = (socklen_t)sizeof addr;
        fd = accept(fdev_fd(apiws->fdev), &addr, &lenaddr);
@@ -153,18 +115,18 @@ static void api_ws_server_accept(struct api_ws *apiws)
                        ERROR("can't hold accepted connection to %s: %m", apiws->uri);
                        close(fd);
                } else {
-                       rc = api_ws_server_accept_client(apiws, fdev);
-                       if (rc < 0)
+                       server = afb_stub_ws_create_server(fdev, &apiws->uri[apiws->offapi], apiws->apiset);
+                       if (!server)
                                ERROR("can't serve accepted connection to %s: %m", apiws->uri);
                }
        }
 }
 
-static int api_ws_server_connect(struct api_ws *apiws);
+static int api_ws_server_connect(struct api_ws_server *apiws);
 
 static void api_ws_server_listen_callback(void *closure, uint32_t revents, struct fdev *fdev)
 {
-       struct api_ws *apiws = closure;
+       struct api_ws_server *apiws = closure;
 
        if ((revents & EPOLLIN) != 0)
                api_ws_server_accept(apiws);
@@ -172,13 +134,13 @@ static void api_ws_server_listen_callback(void *closure, uint32_t revents, struc
                api_ws_server_connect(apiws);
 }
 
-static void api_ws_server_disconnect(struct api_ws *apiws)
+static void api_ws_server_disconnect(struct api_ws_server *apiws)
 {
        fdev_unref(apiws->fdev);
        apiws->fdev = 0;
 }
 
-static int api_ws_server_connect(struct api_ws *apiws)
+static int api_ws_server_connect(struct api_ws_server *apiws)
 {
        /* ensure disconnected */
        api_ws_server_disconnect(apiws);
@@ -200,28 +162,59 @@ static int api_ws_server_connect(struct api_ws *apiws)
 int afb_api_ws_add_server(const char *uri, struct afb_apiset *declare_set, struct afb_apiset *call_set)
 {
        int rc;
-       struct api_ws *apiws;
+       const char *api;
+       struct api_ws_server *apiws;
+       size_t luri, lapi, extra;
+
+       /* check the size */
+       luri = strlen(uri);
+       if (luri > 4000) {
+               ERROR("can't create socket %s", uri);
+               errno = E2BIG;
+               return -1;
+       }
 
-       /* creates the ws api object */
-       apiws = api_ws_make(uri);
-       if (apiws == NULL)
+       /* check the api name */
+       api = afb_socket_api(uri);
+       if (api == NULL || !afb_api_is_valid_name(api)) {
+               ERROR("invalid api name in ws uri %s", uri);
+               errno = EINVAL;
                goto error;
+       }
 
        /* check api name */
-       if (!afb_apiset_lookup(call_set, apiws->api, 1)) {
-               ERROR("Can't provide ws-server for %s: API %s doesn't exist", uri, apiws->api);
-               goto error2;
+       if (!afb_apiset_lookup(call_set, api, 1)) {
+               ERROR("Can't provide ws-server for URI %s: API %s doesn't exist", uri, api);
+               errno = ENOENT;
+               goto error;
        }
 
-       /* connect for serving */
-       rc = api_ws_server_connect(apiws);
-       if (rc < 0)
-               goto error2;
+       /* make the structure */
+       lapi = strlen(api);
+       extra = luri == (api - uri) + lapi ? 0 : lapi + 1;
+       apiws = malloc(sizeof * apiws + luri + extra);
+       if (!apiws) {
+               ERROR("out of memory");
+               errno = ENOMEM;
+               goto error;
+       }
 
        apiws->apiset = afb_apiset_addref(call_set);
-       return 0;
+       apiws->fdev = 0;
+       strcpy(apiws->uri, uri);
+       if (!extra)
+               apiws->offapi = (uint16_t)(api - uri);
+       else {
+               apiws->offapi = (uint16_t)(luri + 1);
+               strcpy(&apiws->uri[apiws->offapi], api);
+       }
+
+       /* connect for serving */
+       rc = api_ws_server_connect(apiws);
+       if (rc >= 0)
+               return 0;
 
-error2:
+       afb_apiset_unref(apiws->apiset);
        free(apiws);
 error:
        return -1;