diff options
-rw-r--r-- | src/afb-api-ws.c | 177 |
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; |