/
githubmirror
/
libteam
Обзор
Документация
Войти
/
githubmirror
/
libteam
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
libteamdctl/cli_zmq.c
266 строк
6 KB
Jiri Pirko
init unitialized value to 0/NULL to silence gcc warnings instead of x=x
19 дек 2014, 18:24
19 дек 2014, 18:24
11967b0
Код
Авторство
О чём код?
/* cli_zmq.c - Teamd daemon control library teamd ZeroMQ library client * Copyright (C) 2013 Jiri Zupka <jzupka@redhat.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #ifdef ENABLE_ZMQ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <sys/types.h> #include <zmq.h> #include <errno.h> #include <unistd.h> #include <teamdctl.h> #include "teamdctl_private.h" #include "../teamd/teamd_zmq_common.h" struct cli_zmq_priv { void *context; void *sock; }; static int cli_zmq_process_msg(struct teamdctl *tdc, char *msg, char **p_replystr) { char *str; char *rest = msg; str = teamd_zmq_msg_getline(&rest); if (!str) { err(tdc, "zmq: Incomplete message.\n"); return -EINVAL;; } if (!strcmp(TEAMD_ZMQ_REPLY_SUCC_PREFIX, str)) { *p_replystr = rest; } else if (!strcmp(TEAMD_ZMQ_REPLY_ERR_PREFIX, str)) { str = teamd_zmq_msg_getline(&rest); if (!str) { err(tdc, "zmq: Incomplete message.\n"); return -EINVAL;; } err(tdc, "zmq: Error message received: \"%s\"", str); str = teamd_zmq_msg_getline(&rest); if (!str) { err(tdc, "zmq: Incomplete message.\n"); return -EINVAL;; } err(tdc, "zmq: Error message content: \"%s\"", str); return -EINVAL;; } else { err(tdc, "zmq: Unsupported message type.\n"); return -EINVAL; } return 0; } static int cli_zmq_send(struct teamdctl *tdc, void *sock, char *buf) { int ret; int buflen = strlen(buf); ret = zmq_send(sock, buf, buflen, 0); if (ret == -1) { warn(tdc, "zmq: send failed: %s", strerror(errno)); return -errno; } free(buf); return 0; } static int cli_zmq_recv(struct teamdctl *tdc, void *sock, char **p_str) { int ret; zmq_msg_t msg; char *buf; if (zmq_msg_init(&msg) == -1) { dbg(tdc, "zmq: Unable initiate message for receive."); return -errno; } ret = zmq_msg_recv(&msg, sock, 0); if (ret == -1) { warn(tdc, "zmq: recv failed: %s", strerror(errno)); return -errno; } buf = malloc(ret + 1); memcpy(buf, zmq_msg_data(&msg), ret); buf[ret] = '\0'; if (zmq_msg_close(&msg) == -1) { free(buf); dbg(tdc, "zmq: Unable close message."); return -errno; } *p_str = buf; return 0; } #define WAIT_MSEC TEAMDCTL_REPLY_TIMEOUT static int myasprintf(char **p_str, const char *fmt, ...) { char *newstr; va_list ap; int ret; va_start(ap, fmt); ret = vasprintf(&newstr, fmt, ap); va_end(ap); if (ret == -1) return -ENOMEM; free(*p_str); *p_str = newstr; return 0; } static int cli_zmq_method_call(struct teamdctl *tdc, const char *method_name, char **p_reply, void *priv, const char *fmt, va_list ap) { struct cli_zmq_priv *cli_zmq = priv; char *str; char *msg = NULL; char *recv_message = NULL; /* gcc needs this initialized */ char *replystr; int err; dbg(tdc, "zmq: Calling method \"%s\"", method_name); err = myasprintf(&msg, "%s\n%s\n", TEAMD_ZMQ_REQUEST_PREFIX, method_name); if (err) return err; while (*fmt) { switch (*fmt++) { case 's': /* string */ str = va_arg(ap, char *); err = myasprintf(&msg, "%s%s\n", msg, str); if (err) goto free_msg; break; default: err(tdc, "zmq: Unknown argument type requested."); err = -EINVAL; goto free_msg; } } err = cli_zmq_send(tdc, cli_zmq->sock, msg); if (err) goto send_err; err = cli_zmq_recv(tdc, cli_zmq->sock, &recv_message); if (err) goto send_err; err = cli_zmq_process_msg(tdc, recv_message, &replystr); if (err) goto free_recv_message; if (p_reply) { replystr = strdup(replystr); if (!replystr) { err = -ENOMEM; goto free_recv_message; } *p_reply = replystr; } free_recv_message: free(recv_message); goto send_err; free_msg: free(msg); send_err: return err; } static int cli_zmq_init(struct teamdctl *tdc, const char *team_name, void *priv) { int err; struct cli_zmq_priv *cli_zmq = priv; void *context, *sock; int recv_timeo; context = zmq_ctx_new(); if (!context) { err(tdc, "zmq: Failed to create context."); return -errno; } sock = zmq_socket(context, ZMQ_REQ); if (!sock) { err(tdc, "zmq: Failed to create socket."); return -errno; } err = zmq_connect(sock, tdc->addr); if (err == -1) { err(tdc, "zmq: Failed to connect socket (%s).", tdc->addr); zmq_close(sock); zmq_ctx_destroy(context); return -errno; } recv_timeo = WAIT_MSEC; err = zmq_setsockopt(sock, ZMQ_RCVTIMEO, &recv_timeo, sizeof(recv_timeo)); if (err == -1) { err(tdc, "zmq: Failed set socket timeout."); zmq_close(sock); zmq_ctx_destroy(context); return -errno; } cli_zmq->sock = sock; cli_zmq->context = context; return 0; } void cli_zmq_fini(struct teamdctl *tdc, void *priv) { struct cli_zmq_priv *cli_zmq = priv; zmq_close(cli_zmq->sock); zmq_ctx_destroy(cli_zmq->context); } static const struct teamdctl_cli cli_zmq = { .name = "zmq", .init = cli_zmq_init, .fini = cli_zmq_fini, .method_call = cli_zmq_method_call, .priv_size = sizeof(struct cli_zmq_priv), }; const struct teamdctl_cli *teamdctl_cli_zmq_get(void) { return &cli_zmq; } #endif /* ENABLE_ZMQ */