X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-api-ws.c;h=611f887c093368a212ea3b6b6cd95ff913159c43;hb=2f7dde4aa74dfa7caba3ddcf125de4693b983c4f;hp=dffe12672c9d3eca6227733ccb17ed6cbfec6707;hpb=a221b08b008c3e3e63dccdbccbcdb7fe8aeb3481;p=src%2Fapp-framework-binder.git diff --git a/src/afb-api-ws.c b/src/afb-api-ws.c index dffe1267..611f887c 100644 --- a/src/afb-api-ws.c +++ b/src/afb-api-ws.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, 2016, 2017 "IoT.bzh" + * Copyright (C) 2015-2018 "IoT.bzh" * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ */ #define _GNU_SOURCE -#define NO_PLUGIN_VERBOSE_MACRO #include #include @@ -30,55 +29,54 @@ #include #include -#include #include "afb-api.h" #include "afb-apiset.h" -#include "afb-common.h" +#include "afb-api-ws.h" +#include "afb-fdev.h" +#include "afb-socket.h" #include "afb-stub-ws.h" #include "verbose.h" -#include "sd-fds.h" +#include "fdev.h" struct api_ws { - char *path; /* path of the object for the API */ + char *uri; /* uri of the object for the API */ char *api; /* api name of the interface */ - int fd; /* file descriptor */ - sd_event_source *listensrc; /**< systemd source for server socket */ + struct fdev *fdev; /* fdev handler */ struct afb_apiset *apiset; }; /******************************************************************************/ /* - * create a structure api_ws not connected to the 'path'. + * create a structure api_ws not connected to the 'uri'. */ -static struct api_ws *api_ws_make(const char *path) +static struct api_ws *api_ws_make(const char *uri) { struct api_ws *api; size_t length; /* allocates the structure */ - length = strlen(path); + length = strlen(uri); api = calloc(1, sizeof *api + 1 + length); if (api == NULL) { errno = ENOMEM; goto error; } - /* path is copied after the struct */ - api->path = (char*)(api+1); - memcpy(api->path, path, length + 1); + /* 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 path */ - while (length && path[length - 1] != '/' && path[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->path[length]; + api->api = &api->uri[length]; if (api->api == NULL || !afb_api_is_valid_name(api->api)) { errno = EINVAL; goto error2; } - api->fd = -1; return api; error2: @@ -87,164 +85,55 @@ error: return NULL; } -static int api_ws_socket_unix(const char *path, int server) -{ - int fd, rc; - struct sockaddr_un addr; - size_t length; - - length = strlen(path); - if (length >= 108) { - errno = ENAMETOOLONG; - return -1; - } - - if (server && path[0] != '@') - unlink(path); - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) - return fd; - - 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 { - rc = connect(fd, (struct sockaddr *) &addr, (socklen_t)(sizeof addr)); - } - if (rc < 0) { - close(fd); - return rc; - } - return fd; -} - -static int api_ws_socket_inet(const char *path, int server) -{ - int rc, fd; - const char *service, *host, *api; - struct addrinfo hint, *rai, *iai; - - /* scan the uri */ - api = strrchr(path, '/'); - service = strrchr(path, ':'); - if (api == NULL || service == NULL || api < service) { - errno = EINVAL; - return -1; - } - host = strndupa(path, service++ - path); - service = strndupa(service, api - service); - - /* get addr */ - memset(&hint, 0, sizeof hint); - hint.ai_family = AF_INET; - hint.ai_socktype = SOCK_STREAM; - rc = getaddrinfo(host, service, &hint, &rai); - if (rc != 0) { - errno = EINVAL; - return -1; - } - - /* get the socket */ - iai = rai; - while (iai != NULL) { - fd = socket(iai->ai_family, iai->ai_socktype, iai->ai_protocol); - if (fd >= 0) { - if (server) { - rc = bind(fd, iai->ai_addr, iai->ai_addrlen); - } else { - rc = connect(fd, iai->ai_addr, iai->ai_addrlen); - } - if (rc == 0) { - freeaddrinfo(rai); - return fd; - } - close(fd); - } - iai = iai->ai_next; - } - freeaddrinfo(rai); - return -1; - -} - -static int api_ws_socket(const char *path, int server) -{ - int fd, rc; - - /* check for systemd socket */ - if (0 == strncmp(path, "sd:", 3)) - fd = sd_fds_for(path + 3); - else { - /* check for unix socket */ - if (0 == strncmp(path, "unix:", 5)) - /* unix socket */ - fd = api_ws_socket_unix(path + 5, server); - else - /* inet socket */ - fd = api_ws_socket_inet(path, server); - - if (fd >= 0 && server) { - rc = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof rc); - rc = listen(fd, 5); - } - } - /* configure the socket */ - if (fd >= 0) { - fcntl(fd, F_SETFD, FD_CLOEXEC); - fcntl(fd, F_SETFL, O_NONBLOCK); - } - return fd; -} - /**********************************************************************************/ -int afb_api_ws_add_client(const char *path, struct afb_apiset *apiset) +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; /* create the ws client api */ - apiws = api_ws_make(path); + apiws = api_ws_make(uri); if (apiws == NULL) goto error; /* connect to the service */ - apiws->fd = api_ws_socket(apiws->path, 0); - if (apiws->fd < 0) { - ERROR("can't connect to ws service %s", apiws->path); + apiws->fdev = afb_socket_open_fdev(apiws->uri, 0); + if (!apiws->fdev) goto error2; - } - stubws = afb_stub_ws_create_client(apiws->fd, apiws->api, apiset); + stubws = afb_stub_ws_create_client(apiws->fdev, apiws->api, call_set); if (!stubws) { - ERROR("can't setup client ws service to %s", apiws->path); + ERROR("can't setup client ws service to %s", apiws->uri); goto error3; } - if (afb_stub_ws_client_add(stubws, apiset) < 0) { - ERROR("can't add the client to the apiset for service %s", apiws->path); - goto error4; + 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; } free(apiws); return 0; -error4: - afb_stub_ws_unref(stubws); error3: - close(apiws->fd); + afb_stub_ws_unref(stubws); error2: free(apiws); error: - return -1; + return -!!strong; +} + +int afb_api_ws_add_client_strong(const char *uri, struct afb_apiset *declare_set, struct afb_apiset *call_set) +{ + return afb_api_ws_add_client(uri, declare_set, call_set, 1); } -static int api_ws_server_accept_client(struct api_ws *apiws, int fd) +int afb_api_ws_add_client_weak(const char *uri, struct afb_apiset *declare_set, struct afb_apiset *call_set) { - return -!afb_stub_ws_create_server(fd, apiws->api, apiws->apiset); + 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); } static void api_ws_server_accept(struct api_ws *apiws) @@ -252,20 +141,28 @@ static void api_ws_server_accept(struct api_ws *apiws) int rc, fd; struct sockaddr addr; socklen_t lenaddr; + struct fdev *fdev; lenaddr = (socklen_t)sizeof addr; - fd = accept(apiws->fd, &addr, &lenaddr); - if (fd >= 0) { - rc = api_ws_server_accept_client(apiws, fd); - if (rc >= 0) - return; - close(fd); + fd = accept(fdev_fd(apiws->fdev), &addr, &lenaddr); + if (fd < 0) { + ERROR("can't accept connection to %s: %m", apiws->uri); + } else { + fdev = afb_fdev_create(fd); + if (!fdev) { + 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) + 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_listen_callback(sd_event_source *src, int fd, uint32_t revents, void *closure) +static void api_ws_server_listen_callback(void *closure, uint32_t revents, struct fdev *fdev) { struct api_ws *apiws = closure; @@ -273,61 +170,46 @@ static int api_ws_server_listen_callback(sd_event_source *src, int fd, uint32_t api_ws_server_accept(apiws); if ((revents & EPOLLHUP) != 0) api_ws_server_connect(apiws); - return 0; } static void api_ws_server_disconnect(struct api_ws *apiws) { - if (apiws->listensrc != NULL) { - sd_event_source_unref(apiws->listensrc); - apiws->listensrc = NULL; - } - if (apiws->fd >= 0) { - close(apiws->fd); - apiws->fd = -1; - } + fdev_unref(apiws->fdev); + apiws->fdev = 0; } static int api_ws_server_connect(struct api_ws *apiws) { - int rc; - /* ensure disconnected */ api_ws_server_disconnect(apiws); /* request the service object name */ - apiws->fd = api_ws_socket(apiws->path, 1); - if (apiws->fd < 0) - ERROR("can't create socket %s", apiws->path); + apiws->fdev = afb_socket_open_fdev(apiws->uri, 1); + if (!apiws->fdev) + ERROR("can't create socket %s", apiws->uri); else { /* listen for service */ - rc = sd_event_add_io(afb_common_get_event_loop(), - &apiws->listensrc, apiws->fd, EPOLLIN, - api_ws_server_listen_callback, apiws); - if (rc >= 0) - return 0; - close(apiws->fd); - errno = -rc; - ERROR("can't add ws object %s", apiws->path); + fdev_set_events(apiws->fdev, EPOLLIN); + fdev_set_callback(apiws->fdev, api_ws_server_listen_callback, apiws); + return 0; } return -1; } /* create the service */ -int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset) +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; - struct afb_api api; /* creates the ws api object */ - apiws = api_ws_make(path); + apiws = api_ws_make(uri); if (apiws == NULL) goto error; /* check api name */ - if (afb_apiset_get(apiset, apiws->api, &api)) { - ERROR("Can't provide ws-server for %s: API %s doesn't exist", path, apiws->api); + 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; } @@ -336,7 +218,7 @@ int afb_api_ws_add_server(const char *path, struct afb_apiset *apiset) if (rc < 0) goto error2; - apiws->apiset = afb_apiset_addref(apiset); + apiws->apiset = afb_apiset_addref(call_set); return 0; error2: @@ -344,5 +226,3 @@ error2: error: return -1; } - -