summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/afb-api-ws.c177
1 files changed, 85 insertions, 92 deletions
diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c
index 611f887c..6d8506c1 100644
--- a/src/afb-api-ws.c
+++ b/src/afb-api-ws.c
@@ -38,85 +38,47 @@
#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;