The branch, master has been updated via dccd963 ctdb-client: Use sock_client abstraction for eventd client via dcc1eaf ctdb-common: Add sock_client abstraction via dfa8786 ctdb-protocol: Drop struct ctdb_event_header via 164d65a ctdb-protocol: Replace ctdb_event_header with sock_packet_header via 1787a4b ctdb-protocol: Add a generic packet header from 15c9177 ctdb-common: Parse IPv4-mapped IPv6 addresses into IPv4 addresses
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit dccd9630fb6d82cbf79374c75cd305987c9c9eb8 Author: Amitay Isaacs <ami...@gmail.com> Date: Thu Jun 29 16:25:57 2017 +1000 ctdb-client: Use sock_client abstraction for eventd client Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Martin Schwenke <mar...@meltin.net> Autobuild-User(master): Martin Schwenke <mart...@samba.org> Autobuild-Date(master): Fri Sep 1 12:49:27 CEST 2017 on sn-devel-144 commit dcc1eaf542e279bf05c338fd03bc9307084cadc5 Author: Amitay Isaacs <ami...@gmail.com> Date: Thu Jun 29 15:10:11 2017 +1000 ctdb-common: Add sock_client abstraction This sets up boilerplate required for a client code connecting to a server over unix domain socket. The communication between client and server is "request" from client to server and "reply" from server to client. Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Martin Schwenke <mar...@meltin.net> commit dfa87862fb3f2c17094bb8ac921b369c344c556d Author: Amitay Isaacs <ami...@gmail.com> Date: Tue Jul 11 02:16:24 2017 +1000 ctdb-protocol: Drop struct ctdb_event_header Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Martin Schwenke <mar...@meltin.net> commit 164d65ace283188d00224dd1e001b8776d393fd8 Author: Amitay Isaacs <ami...@gmail.com> Date: Mon Jul 10 18:35:12 2017 +1000 ctdb-protocol: Replace ctdb_event_header with sock_packet_header This removes the static declaration and adds prototype declarations of ctdb_event_header marshalling functions to avoid compiler warnings. These functions will be removed. Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Martin Schwenke <mar...@meltin.net> commit 1787a4b63292aee0e9df4e4031188ac239d804d8 Author: Amitay Isaacs <ami...@gmail.com> Date: Fri Jul 7 17:21:54 2017 +1000 ctdb-protocol: Add a generic packet header This will avoid duplication when new daemons (and new client-server protocols) are created out of the main ctdb daemon. Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Martin Schwenke <mar...@meltin.net> ----------------------------------------------------------------------- Summary of changes: ctdb/client/client_event.c | 297 +++++++---------------------- ctdb/common/sock_client.c | 332 +++++++++++++++++++++++++++++++++ ctdb/common/sock_client.h | 129 +++++++++++++ ctdb/protocol/protocol.h | 18 +- ctdb/protocol/protocol_api.h | 15 +- ctdb/protocol/protocol_event.c | 61 +----- ctdb/protocol/protocol_sock.c | 81 ++++++++ ctdb/server/ctdb_eventd.c | 3 +- ctdb/server/eventscript.c | 3 +- ctdb/tests/cunit/protocol_test_102.sh | 1 - ctdb/tests/src/protocol_common.c | 13 ++ ctdb/tests/src/protocol_common.h | 4 + ctdb/tests/src/protocol_common_event.c | 21 +-- ctdb/tests/src/protocol_common_event.h | 4 - ctdb/tests/src/protocol_event_test.c | 32 +--- ctdb/tests/src/protocol_types_test.c | 5 + ctdb/wscript | 6 +- 17 files changed, 679 insertions(+), 346 deletions(-) create mode 100644 ctdb/common/sock_client.c create mode 100644 ctdb/common/sock_client.h create mode 100644 ctdb/protocol/protocol_sock.c Changeset truncated at 500 lines: diff --git a/ctdb/client/client_event.c b/ctdb/client/client_event.c index 533ed39..7111fe7 100644 --- a/ctdb/client/client_event.c +++ b/ctdb/client/client_event.c @@ -18,7 +18,6 @@ */ #include "replace.h" -#include "system/filesys.h" #include "system/network.h" #include <talloc.h> @@ -28,301 +27,149 @@ #include "lib/util/tevent_unix.h" #include "common/logging.h" -#include "common/reqid.h" -#include "common/comm.h" +#include "common/sock_client.h" #include "protocol/protocol_api.h" #include "client/client_event.h" struct ctdb_event_context { - struct reqid_context *idr; - struct comm_context *comm; - int fd; - - ctdb_client_callback_func_t callback; - void *private_data; + struct sock_client_context *sockc; }; -static int ctdb_event_connect(struct ctdb_event_context *eclient, - struct tevent_context *ev, - const char *sockpath); - -static int ctdb_event_context_destructor(struct ctdb_event_context *eclient); - -int ctdb_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - const char *sockpath, struct ctdb_event_context **out) +static int ctdb_event_msg_request_push(void *request_data, uint32_t reqid, + TALLOC_CTX *mem_ctx, + uint8_t **buf, size_t *buflen, + void *private_data) { - struct ctdb_event_context *eclient; + struct ctdb_event_request *request = + (struct ctdb_event_request *)request_data; int ret; - eclient = talloc_zero(mem_ctx, struct ctdb_event_context); - if (eclient == NULL) { - DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n")); - return ENOMEM; - } + sock_packet_header_set_reqid(&request->header, reqid); - ret = reqid_init(eclient, INT_MAX-200, &eclient->idr); - if (ret != 0) { - DEBUG(DEBUG_ERR, ("reqid_init() failed, ret=%d\n", ret)); - talloc_free(eclient); - return ret; + *buflen = ctdb_event_request_len(request); + *buf = talloc_size(mem_ctx, *buflen); + if (*buf == NULL) { + return ENOMEM; } - eclient->fd = -1; - - ret = ctdb_event_connect(eclient, ev, sockpath); + ret = ctdb_event_request_push(request, *buf, buflen); if (ret != 0) { - talloc_free(eclient); return ret; } - talloc_set_destructor(eclient, ctdb_event_context_destructor); - - *out = eclient; return 0; } -static int ctdb_event_context_destructor(struct ctdb_event_context *eclient) +static int ctdb_event_msg_reply_pull(uint8_t *buf, size_t buflen, + TALLOC_CTX *mem_ctx, void **reply_data, + void *private_data) { - if (eclient->fd != -1) { - close(eclient->fd); - eclient->fd = -1; - } - return 0; -} - -static void event_read_handler(uint8_t *buf, size_t buflen, - void *private_data); -static void event_dead_handler(void *private_data); - -static int ctdb_event_connect(struct ctdb_event_context *eclient, - struct tevent_context *ev, const char *sockpath) -{ - struct sockaddr_un addr; - size_t len; - int fd, ret; - - if (sockpath == NULL) { - DEBUG(DEBUG_ERR, ("socket path cannot be NULL\n")); - return EINVAL; - } + struct ctdb_event_reply *reply; + int ret; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path)); - if (len >= sizeof(addr.sun_path)) { - DEBUG(DEBUG_ERR, ("socket path too long, len=%zu\n", - strlen(sockpath))); - return ENAMETOOLONG; + reply = talloc_zero(mem_ctx, struct ctdb_event_reply); + if (reply == NULL) { + return ENOMEM; } - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - ret = errno; - DEBUG(DEBUG_ERR, ("socket() failed, errno=%d\n", ret)); + ret = ctdb_event_reply_pull(buf, buflen, reply, reply); + if (ret != 0) { + talloc_free(reply); return ret; } - ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1) { - ret = errno; - DEBUG(DEBUG_ERR, ("connect() failed, errno=%d\n", ret)); - close(fd); - return ret; - } - eclient->fd = fd; + *reply_data = reply; + return 0; +} - ret = comm_setup(eclient, ev, fd, event_read_handler, eclient, - event_dead_handler, eclient, &eclient->comm); +static int ctdb_event_msg_reply_reqid(uint8_t *buf, size_t buflen, + uint32_t *reqid, void *private_data) +{ + struct sock_packet_header header; + size_t np; + int ret; + + ret = sock_packet_header_pull(buf, buflen, &header, &np); if (ret != 0) { - DEBUG(DEBUG_ERR, ("comm_setup() failed, ret=%d\n", ret)); - close(fd); - eclient->fd = -1; return ret; } + *reqid = header.reqid; return 0; } -static void ctdb_event_msg_reply(struct ctdb_event_context *eclient, - uint8_t *buf, size_t buflen); +struct sock_client_proto_funcs event_proto_funcs = { + .request_push = ctdb_event_msg_request_push, + .reply_pull = ctdb_event_msg_reply_pull, + .reply_reqid = ctdb_event_msg_reply_reqid, +}; -static void event_read_handler(uint8_t *buf, size_t buflen, - void *private_data) + +int ctdb_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *sockpath, struct ctdb_event_context **out) { - struct ctdb_event_context *eclient = talloc_get_type_abort( - private_data, struct ctdb_event_context); + struct ctdb_event_context *eclient; + int ret; - ctdb_event_msg_reply(eclient, buf, buflen); -} + eclient = talloc_zero(mem_ctx, struct ctdb_event_context); + if (eclient == NULL) { + DEBUG(DEBUG_ERR, (__location__ " memory allocation error\n")); + return ENOMEM; + } -static void event_dead_handler(void *private_data) -{ - struct ctdb_event_context *eclient = talloc_get_type_abort( - private_data, struct ctdb_event_context); - ctdb_client_callback_func_t callback = eclient->callback; - void *callback_data = eclient->private_data; - - talloc_free(eclient); - if (callback != NULL) { - callback(callback_data); - return; + ret = sock_client_setup(eclient, ev, sockpath, + &event_proto_funcs, eclient, + &eclient->sockc); + if (ret != 0) { + talloc_free(eclient); + return ret; } - DEBUG(DEBUG_NOTICE, ("connection to daemon closed, exiting\n")); - exit(1); + *out = eclient; + return 0; } void ctdb_event_set_disconnect_callback(struct ctdb_event_context *eclient, ctdb_client_callback_func_t callback, void *private_data) { - eclient->callback = callback; - eclient->private_data = private_data; + sock_client_set_disconnect_callback(eclient->sockc, + callback, private_data); } /* * Handle eventd_request and eventd_reply */ -struct ctdb_event_msg_state { - struct ctdb_event_context *eclient; - - uint32_t reqid; - struct tevent_req *req; - struct ctdb_event_reply *reply; -}; - -static int ctdb_event_msg_state_destructor(struct ctdb_event_msg_state *state); -static void ctdb_event_msg_done(struct tevent_req *subreq); - struct tevent_req *ctdb_event_msg_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct ctdb_event_context *eclient, struct ctdb_event_request *request) { - struct tevent_req *req, *subreq; - struct ctdb_event_msg_state *state; - uint8_t *buf; - size_t buflen; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct ctdb_event_msg_state); - if (req == NULL) { - return NULL; - } - - state->eclient = eclient; - - state->reqid = reqid_new(eclient->idr, state); - if (state->reqid == REQID_INVALID) { - talloc_free(req); - return NULL; - } - state->req = req; - - talloc_set_destructor(state, ctdb_event_msg_state_destructor); - - ctdb_event_header_fill(&request->header, state->reqid); - - buflen = ctdb_event_request_len(request); - buf = talloc_size(state, buflen); - if (tevent_req_nomem(buf, req)) { - return tevent_req_post(req, ev); - } - - ret = ctdb_event_request_push(request, buf, &buflen); - if (ret != 0) { - tevent_req_error(req, ret); - return tevent_req_post(req, ev); - } - - subreq = comm_write_send(state, ev, eclient->comm, buf, buflen); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, ctdb_event_msg_done, req); + struct tevent_req *req; + req = sock_client_msg_send(mem_ctx, ev, eclient->sockc, + tevent_timeval_zero(), request); return req; } -static int ctdb_event_msg_state_destructor(struct ctdb_event_msg_state *state) -{ - reqid_remove(state->eclient->idr, state->reqid); - return 0; -} - -static void ctdb_event_msg_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - int ret; - bool status; - - status = comm_write_recv(subreq, &ret); - TALLOC_FREE(subreq); - if (! status) { - tevent_req_error(req, ret); - return; - } - - /* Wait for the reply or timeout */ -} - -static void ctdb_event_msg_reply(struct ctdb_event_context *eclient, - uint8_t *buf, size_t buflen) -{ - struct ctdb_event_reply *reply; - struct ctdb_event_msg_state *state; - int ret; - - reply = talloc_zero(eclient, struct ctdb_event_reply); - if (reply == NULL) { - D_WARNING("memory allocation error\n"); - return; - } - - ret = ctdb_event_reply_pull(buf, buflen, reply, reply); - if (ret != 0) { - D_WARNING("Invalid packet received, ret=%d\n", ret); - return; - } - - state = reqid_find(eclient->idr, reply->header.reqid, - struct ctdb_event_msg_state); - if (state == NULL) { - return; - } - - if (reply->header.reqid != state->reqid) { - return; - } - - state->reply = talloc_steal(state, reply); - tevent_req_done(state->req); -} - bool ctdb_event_msg_recv(struct tevent_req *req, int *perr, TALLOC_CTX *mem_ctx, struct ctdb_event_reply **reply) { - struct ctdb_event_msg_state *state = tevent_req_data( - req, struct ctdb_event_msg_state); - int ret; + void *reply_data; + bool status; - if (tevent_req_is_unix_error(req, &ret)) { - if (perr != NULL) { - *perr = ret; - } - return false; - } + status = sock_client_msg_recv(req, perr, mem_ctx, &reply_data); - if (reply != NULL) { - *reply = talloc_steal(mem_ctx, state->reply); + if (status && reply != NULL) { + *reply = talloc_get_type_abort( + reply_data, struct ctdb_event_reply); } - return true; + return status; } /* diff --git a/ctdb/common/sock_client.c b/ctdb/common/sock_client.c new file mode 100644 index 0000000..e5f993e --- /dev/null +++ b/ctdb/common/sock_client.c @@ -0,0 +1,332 @@ +/* + A client based on unix domain socket + + Copyright (C) Amitay Isaacs 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/network.h" + +#include <talloc.h> +#include <tevent.h> + +#include "lib/util/debug.h" +#include "lib/util/time.h" +#include "lib/util/tevent_unix.h" + +#include "common/logging.h" +#include "common/reqid.h" +#include "common/comm.h" +#include "common/sock_client.h" + +struct sock_client_context { + struct sock_client_proto_funcs *funcs; + void *private_data; + + void (*disconnect_callback)(void *private_data); + void *disconnect_data; + + int fd; + struct comm_context *comm; + struct reqid_context *idr; +}; + +/* + * connect to a unix domain socket + */ + +static int socket_connect(const char *sockpath) +{ + struct sockaddr_un addr; + size_t len; + int fd, ret; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + + len = strlcpy(addr.sun_path, sockpath, sizeof(addr.sun_path)); + if (len >= sizeof(addr.sun_path)) { + D_ERR("socket path too long: %s\n", sockpath); + return -1; + } + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + D_ERR("socket create failed - %s\n", sockpath); + return -1; + } + + ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret != 0) { + D_ERR("socket connect failed - %s\n", sockpath); + close(fd); + return -1; + } + + return fd; +} + +/* + * Socket client + */ + +static int sock_client_context_destructor(struct sock_client_context *sockc); +static void sock_client_read_handler(uint8_t *buf, size_t buflen, + void *private_data); +static void sock_client_dead_handler(void *private_data); + +static void sock_client_msg_reply(struct sock_client_context *sockc, + uint8_t *buf, size_t buflen); + +int sock_client_setup(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *sockpath, + struct sock_client_proto_funcs *funcs, + void *private_data, + struct sock_client_context **result) +{ + struct sock_client_context *sockc; + int ret; + + if (sockpath == NULL) { + return EINVAL; + } + + if (funcs == NULL || funcs->request_push == NULL || -- Samba Shared Repository