From patchwork Wed Aug 18 05:32:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 1517910 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2607:f8b0:4864:20::b3b; helo=mail-yb1-xb3b.google.com; envelope-from=swupdate+bncbcl4hcw73qcbbcvx6keamgqeszfxaay@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20161025 header.b=CzOhuBRi; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=eB42DFdQ; dkim-atps=neutral Received: from mail-yb1-xb3b.google.com (mail-yb1-xb3b.google.com [IPv6:2607:f8b0:4864:20::b3b]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GqGl31Zlsz9sVw for ; Wed, 18 Aug 2021 15:33:01 +1000 (AEST) Received: by mail-yb1-xb3b.google.com with SMTP id v130-20020a25c5880000b0290593c8c353ffsf1703782ybe.7 for ; Tue, 17 Aug 2021 22:33:01 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1629264778; cv=pass; d=google.com; s=arc-20160816; b=RwElFRIE1s5KrVw+syy5/83tHwqrAJONYQmaASf/Jth07Jyk0ZvJXt6vPOcp0Xtikr bbqoAr4BQThxDpNTjtcxegbcFxapHTBH8fLUOUUGHUdtnMjmRxL0wcyMNavmEizybLSF cb4LQox16SYCRjPdmgRqEgUXj0xUNrKs7iWT2CtQnktFC8/9jl1U906cgzdZed7VK62x LZSdM1bIUYn23KdlT+c7ex2tKEDTeiOjMowetWzquvcAm3y9Q3F4grjlydlYIO/Qj9UO QjDjvs0mj2pfixcYQWVI+T8UvoA4cgYB9LprsHZoHgwDrNNfNxenUiELt+XIo9Zq2s6n zVwA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:mime-version:message-id:date :subject:cc:to:from:sender:dkim-signature:dkim-signature; bh=0HYYdGaBXPutLofzGR/6z0R5K1xvpEnKYSSem+S8ISI=; b=py+Rv2pUcdDYu3CB+A+KTQXdgTgZS6Rc6OTYOUhvxRLp6d53VfU5VRbkuSvJLbmxk0 legMMZ5b3rtuUCT1Eaf86rllmYSztULHR5QTT5nlc/QSeLdL3f0DOKWIGbZCLR90F9GJ JglkWheeEdTCclM0SDTqkGjTDT4p6iNDgmwCgByhJrjDJF6LTyvoHQrj4s1T5fCyj10G l6UKkiFl1dXKTrNEcOVGREtivSknsRyt6qjnGpUJiyGmHdFJwjxjTp+dB6OPCIdxrigQ ykUWpRC8mdc+YEo5yDQhVKIDfXf+boVzTvlYZBeFjb9GVS/MMkLy52IuQkd1td+C+2gR OHbw== ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=O+S7T2gB; spf=pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::22f as permitted sender) smtp.mailfrom=james.hilliard1@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:mime-version :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=0HYYdGaBXPutLofzGR/6z0R5K1xvpEnKYSSem+S8ISI=; b=CzOhuBRia+i4FRLASUngqWZWMmz9EJa5ImcIb9GcbDP7j7/SHNRSBWZHbC34BPhlFh uvpSI7Jsk7jl3eKl3bKXMvsw9pQtJTOPCLSDIhJmB4dqUhFqND/+yVfj34lOsxppBeEr E/jl8L1VN8OueI2e+f11wQOVtrnoczdteBWyV3P2x4cpZf+Muh8IwNmTngsdFBBdAftx qLRoDBVSX2686wadzwhow85AHaqOZYAaAjFxJN+eU82h0vLBPRf8qwSMoiRrjfo/XcGH mmYwwjmOS7bFZV0UYa2dIn+skzjT3nhj4bmD7yFicXZCC1xz1XjR9uwbwg0oYUC5PPES DWzw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-subscribe:list-unsubscribe; bh=0HYYdGaBXPutLofzGR/6z0R5K1xvpEnKYSSem+S8ISI=; b=eB42DFdQAP3RU4gnpJbJwtIRN0kB/hqSdTjhMAM8oH+dgXEEgdf/XbmmTsFXD12bue IGfpmKsQMxmyunrz9IFo6HNImyn/aIeGcIbB8MT4P4m62lo29aBQ0ouOZ7uWzSTAzBew chxbssw3KU8C/oTuZ/48qeJrtn+2jeK1horHJVH7P3kzj9uGu2fC92bpEse+aDxtEpSt IKxCb2Y/iNdmwI3XJgyT3yqvDzC6gmdZlFRp6Mjrq4sctqen21hCozwYrODNJF6OuAse INHSj4RuWWHBoKfUYAmBpvh90DBXeXuNtIlPugd+q9RKHAjO4sHqBPfiKVbdGyioLCzo AqMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:from:to:cc:subject:date:message-id :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post :list-help:list-archive:list-subscribe:list-unsubscribe; bh=0HYYdGaBXPutLofzGR/6z0R5K1xvpEnKYSSem+S8ISI=; b=IyNrdukAKNC30JJHdILPpGF/T+qmszSQIOtYPQRwGQqvQ+aO1WPNF2KCgIJa+nEwfb e2fufUalpg+xq2hN+OyrnHYDK8QxKIf8dXSBp6gTBsYKl5H+juTz6h3FlO+Ee+PdBgq0 KHIF0qdp4wjdL639EjmND9KasqvLDqNeDPv31LLEH/BnRYnaet+y2UlnBUbn+9VMcEZl 3rJ1pO0W0/0VnXbi8bRBYu8OrdhwOUUwOkujQNPcCcJxCAoa4JDlt+JizdnSVI1LFMZo Qlf8F4iLSAR96ybGd7FE8wIXWRz+5T95wUVyubMTRU22eYLCWPqJ5qoWIlAvwg7NALSk cVGQ== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM530o2IbkIIa59qm7p4loc1iJhHw1p2O7exYLbeIq8VYmN1dkmhgp Nz8nFlpkyPQXVNvSf7kirWc= X-Google-Smtp-Source: ABdhPJzwRw4B293b1vNfilsN7YlHXLDFJXf9qZnuZzMZRMVU5lDQZAKv4C9MsUOxudnjmbz6VnPerw== X-Received: by 2002:a25:8810:: with SMTP id c16mr8687272ybl.383.1629264778519; Tue, 17 Aug 2021 22:32:58 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a25:2b08:: with SMTP id r8ls552345ybr.9.gmail; Tue, 17 Aug 2021 22:32:58 -0700 (PDT) X-Received: by 2002:a5b:587:: with SMTP id l7mr9656715ybp.208.1629264777965; Tue, 17 Aug 2021 22:32:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629264777; cv=none; d=google.com; s=arc-20160816; b=Vyvo15nWlmUPHiOmOkugB1oTVVOCpYZQWqor7G1HK6/4hZm2BF8hYCpt37m5V8lL7h o9vDMmnz6b+rBiNU4Gab1RE8gMYQB7wxYhQhkuW1FMjUXEbT1HqqZzoPc5hyywhF+Kvo EtHQlTWubaGXrSJQBondGQOmMiRZ4g3Bqup0pRxMB7f/GlnHjbkIA2MpoUzuFplQSl8Q UdcmmIVaPLbYv11kOTdFUSuj7Ntql/L1mPsKvKXMLMHF0J04OECQ9xC4rSzQKNrOEcvy 7cYZ8JIWDl5z9RDaTOfrN47Az9JYBefcdsiusQD1DV6yUlaa8/yrs1WrB4NOgLIk/DK1 JSTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:dkim-signature; bh=sJGMQ7ZOGUYlhwYUmO+zVKz5zdSyKIieYX3IRBdBESk=; b=b486AUvjpqwbQOSdciI57BAuVuWPtthP9wtve+/+MOLxyCN9Cyx/iKRJIhuDhw/6Af 1lmwcSQw50lsHAJS+NlYtUnJrSQHubX8XKe4SXZSxqE6KO3FWljOI70KgKUcFen58j2M CRKnXVMvt4YPaKaDFwPK59ZauquA8Ck6LWKU/Ac+dAjEV0SH6vbXiSIj6YiPpelKvwmM PbnJZjIQrUFtU+pGsFOlodq0DqpCBlLkGue0rYZLdpPFKQZZ0sCctznhU5gMxSgbdWMk j878P1soQFVkq7uiMwZ/sLCpulqEAM6uotISpsQO71ehLnPiaZaP+NAcCRm/F2e6r2UZ LImw== ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=O+S7T2gB; spf=pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::22f as permitted sender) smtp.mailfrom=james.hilliard1@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com. [2607:f8b0:4864:20::22f]) by gmr-mx.google.com with ESMTPS id z205si371731ybb.0.2021.08.17.22.32.57 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 17 Aug 2021 22:32:57 -0700 (PDT) Received-SPF: pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::22f as permitted sender) client-ip=2607:f8b0:4864:20::22f; Received: by mail-oi1-x22f.google.com with SMTP id bd1so2929252oib.3 for ; Tue, 17 Aug 2021 22:32:57 -0700 (PDT) X-Received: by 2002:aca:c614:: with SMTP id w20mr5740694oif.18.1629264777205; Tue, 17 Aug 2021 22:32:57 -0700 (PDT) Received: from MacBook-Pro.localdomain ([143.131.12.67]) by smtp.gmail.com with ESMTPSA id o18sm1028072oiw.27.2021.08.17.22.32.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Aug 2021 22:32:56 -0700 (PDT) From: James Hilliard To: swupdate@googlegroups.com Cc: James Hilliard Subject: [swupdate] [PATCH v2 1/1] IPC: add status streaming support Date: Tue, 17 Aug 2021 23:32:51 -0600 Message-Id: <20210818053251.49418-1-james.hilliard1@gmail.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 X-Original-Sender: james.hilliard1@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=O+S7T2gB; spf=pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::22f as permitted sender) smtp.mailfrom=james.hilliard1@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , This adds a NOTIFY_STREAM command to the ctrl interface, this is implemented with a history replay functionality so that clients can see notify messages from before they connect. This has the advantage of making it possible for multiple clients to monitor notify messages at the same time. Signed-off-by: James Hilliard --- Changes v1 -> v2: - move stream interface into network_ipc ctrl socket - add history replay --- core/network_thread.c | 127 +++++++++++++++++++++++++++++++++- include/network_ipc.h | 11 ++- ipc/network_ipc.c | 79 +++++++++++++++++++++ mongoose/mongoose_interface.c | 39 +++++++---- 4 files changed, 241 insertions(+), 15 deletions(-) diff --git a/core/network_thread.c b/core/network_thread.c index adaf21c..5c46f93 100644 --- a/core/network_thread.c +++ b/core/network_thread.c @@ -69,6 +69,14 @@ static pthread_t subprocess_ipc_handler_thread_id; static pthread_mutex_t subprocess_msg_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t subprocess_wkup = PTHREAD_COND_INITIALIZER; +struct notify_conn { + SIMPLEQ_ENTRY(notify_conn) next; + int sockfd; +}; + +SIMPLEQ_HEAD(connections, notify_conn); +static struct connections notify_conns; + static bool is_selection_allowed(const char *software_set, char *running_mode, struct dict const *acceptedlist) { @@ -116,11 +124,61 @@ static void clean_msg(char *msg, char drop) } } +static int write_notify_msg(ipc_message *msg, int sockfd) +{ + void *buf; + size_t count; + ssize_t n; + int ret = 0; + + buf = msg; + count = sizeof(*msg); + while (count > 0) { + n = send(sockfd, buf, count, MSG_NOSIGNAL); + if (n <= 0) { + /* + * We can't use the notify methods for error logging here as it will cause a deadlock. + */ + if (n == 0) { + fprintf(stderr, "Error: A status client is not responding, removing it.\n"); + } else { + fprintf(stderr, "A status client disappeared, removing it: %s\n", strerror(errno)); + } + ret = -1; + break; + } + count -= (size_t)n; + buf = (char*)buf + n; + } + return ret; +} + +/* + * This must be called after acquiring the mutex + * for the msglock structure + */ +static void send_notify_msg(ipc_message *msg) +{ + struct notify_conn *conn, *tmp; + int ret; + + SIMPLEQ_FOREACH_SAFE(conn, ¬ify_conns, next, tmp) { + ret = write_notify_msg(msg, conn->sockfd); + if (ret < 0) { + close(conn->sockfd); + SIMPLEQ_REMOVE(¬ify_conns, conn, + notify_conn, next); + free(conn); + } + } +} + static void network_notifier(RECOVERY_STATUS status, int error, int level, const char *msg) { int len = msg ? strlen(msg) : 0; struct msg_elem *newmsg = (struct msg_elem *)calloc(1, sizeof(*newmsg) + len + 1); struct msg_elem *oldmsg; + ipc_message ipcmsg; if (!newmsg) return; @@ -148,6 +206,18 @@ static void network_notifier(RECOVERY_STATUS status, int error, int level, const SIMPLEQ_INSERT_TAIL(¬ifymsgs, newmsg, next); + + ipcmsg.magic = IPC_MAGIC; + ipcmsg.type = NOTIFY_STREAM; + memset(ipcmsg.data.msg, 0, sizeof(ipcmsg.data.msg)); + + strncpy(ipcmsg.data.notify.msg, newmsg->msg, + sizeof(ipcmsg.data.notify.msg) - 1); + ipcmsg.data.notify.status = newmsg->status; + ipcmsg.data.notify.error = newmsg->error; + ipcmsg.data.notify.level = newmsg->level; + send_notify_msg(&ipcmsg); + pthread_mutex_unlock(&msglock); } @@ -366,7 +436,8 @@ void *network_thread (void *data) struct sockaddr_un cliaddr; ipc_message msg; int nread; - struct msg_elem *notification; + struct msg_elem *notification, *tmp; + struct notify_conn *conn; int ret; update_state_t value; struct subprocess_msg_elem *subprocess_msg; @@ -378,6 +449,7 @@ void *network_thread (void *data) } SIMPLEQ_INIT(¬ifymsgs); + SIMPLEQ_INIT(¬ify_conns); SIMPLEQ_INIT(&subprocess_messages); register_notifier(network_notifier); @@ -507,6 +579,59 @@ void *network_thread (void *data) } pthread_mutex_unlock(&msglock); + break; + case NOTIFY_STREAM: + msg.type = ACK; + memset(msg.data.msg, 0, sizeof(msg.data.msg)); + msg.data.status.current = instp->status; + msg.data.status.last_result = instp->last_install; + msg.data.status.error = instp->last_error; + + ret = write(ctrlconnfd, &msg, sizeof(msg)); + msg.type = NOTIFY_STREAM; + if (ret < 0) { + ERROR("Error write notify ack on socket ctrl"); + close(ctrlconnfd); + break; + } + + /* Get first notification from the queue */ + pthread_mutex_lock(&msglock); + notification = SIMPLEQ_FIRST(¬ifymsgs); + + /* Send notify history */ + SIMPLEQ_FOREACH_SAFE(notification, ¬ifymsgs, next, tmp) { + memset(msg.data.msg, 0, sizeof(msg.data.msg)); + + strncpy(msg.data.notify.msg, notification->msg, + sizeof(msg.data.notify.msg) - 1); + msg.data.notify.status = notification->status; + msg.data.notify.error = notification->error; + msg.data.notify.level = notification->level; + + ret = write_notify_msg(&msg, ctrlconnfd); + if (ret < 0) { + pthread_mutex_unlock(&msglock); + ERROR("Error write notify history on socket ctrl"); + close(ctrlconnfd); + break; + } + } + + /* + * Save the new connection to send notifications to + */ + conn = (struct notify_conn *)calloc(1, sizeof(*conn)); + if (!conn) { + pthread_mutex_unlock(&msglock); + ERROR("Out of memory, skipping..."); + close(ctrlconnfd); + continue; + } + conn->sockfd = ctrlconnfd; + SIMPLEQ_INSERT_TAIL(¬ify_conns, conn, next); + pthread_mutex_unlock(&msglock); + break; case SET_AES_KEY: #ifndef CONFIG_PKCS11 diff --git a/include/network_ipc.h b/include/network_ipc.h index 1a3d957..f370ccf 100644 --- a/include/network_ipc.h +++ b/include/network_ipc.h @@ -37,7 +37,8 @@ typedef enum { SET_UPDATE_STATE, /* set bootloader ustate */ GET_UPDATE_STATE, REQ_INSTALL_EXT, - SET_VERSIONS_RANGE + SET_VERSIONS_RANGE, + NOTIFY_STREAM } msgtype; /* @@ -80,6 +81,12 @@ typedef union { int error; char desc[2048]; } status; + struct { + int status; + int error; + int level; + char msg[2048]; + } notify; struct { struct swupdate_request req; unsigned int len; /* Len of data valid in buf */ @@ -122,6 +129,8 @@ int ipc_send_data(int connfd, char *buf, int size); void ipc_end(int connfd); int ipc_get_status(ipc_message *msg); int ipc_get_status_timeout(ipc_message *msg, unsigned int timeout_ms); +int ipc_notify_connect(void); +int ipc_notify_receive(int *connfd, ipc_message *msg); int ipc_postupdate(ipc_message *msg); int ipc_send_cmd(ipc_message *msg); diff --git a/ipc/network_ipc.c b/ipc/network_ipc.c index 767079d..5ccc18b 100644 --- a/ipc/network_ipc.c +++ b/ipc/network_ipc.c @@ -163,6 +163,85 @@ int ipc_get_status_timeout(ipc_message *msg, unsigned int timeout_ms) return ret == 0 ? sizeof(*msg) : -1; } +static int __ipc_start_notify(int connfd, ipc_message *msg, unsigned int timeout_ms) +{ + fd_set fds; + struct timeval tv; + + memset(msg, 0, sizeof(*msg)); + msg->magic = IPC_MAGIC; + msg->type = NOTIFY_STREAM; + + if (write(connfd, msg, sizeof(*msg)) != sizeof(*msg)) + return -1; + + if (timeout_ms) { + FD_ZERO(&fds); + FD_SET(connfd, &fds); + + /* + * Invalid the message + * Caller should check it + */ + msg->magic = 0; + + tv.tv_sec = 0; + tv.tv_usec = timeout_ms * 1000; + if ((select(connfd + 1, &fds, NULL, NULL, &tv) <= 0) || + !FD_ISSET(connfd, &fds)) + return -ETIMEDOUT; + } + + return -(read(connfd, msg, sizeof(*msg)) != sizeof(*msg)); +} + +int ipc_notify_connect(void) +{ + int ret; + int connfd; + ipc_message msg; + + connfd = prepare_ipc(); + if (connfd < 0) + return -1; + + /* + * Initialize the notify stream + */ + ret = __ipc_start_notify(connfd, &msg, 0); + if (ret || msg.type != ACK) { + fprintf(stdout, "Notify connection handshake failed..\n"); + close(connfd); + return ret; + } + + return connfd; +} + +int ipc_notify_receive(int *connfd, ipc_message *msg) +{ + int ret = read(*connfd, msg, sizeof(*msg)); + + if (ret == -1 && (errno == EAGAIN || errno == EINTR)) + return 0; + + if (ret != sizeof(*msg)) { + fprintf(stdout, "Connection closing..\n"); + close(*connfd); + *connfd = -1; + return -1; + } + + if (msg->magic != IPC_MAGIC) { + fprintf(stdout, "Connection closing, invalid magic...\n"); + close(*connfd); + *connfd = -1; + return -1; + } + + return ret; +} + int ipc_inst_start_ext(void *priv, ssize_t size) { int connfd; diff --git a/mongoose/mongoose_interface.c b/mongoose/mongoose_interface.c index 2e9416b..1878101 100644 --- a/mongoose/mongoose_interface.c +++ b/mongoose/mongoose_interface.c @@ -141,31 +141,44 @@ static void broadcast(struct mg_mgr *mgr, char *str) static void *broadcast_message_thread(void *data) { + int fd = -1; + for (;;) { ipc_message msg; - int ret = ipc_get_status(&msg); + int ret; - if (!ret && strlen(msg.data.status.desc) != 0) { + if (fd < 0) + fd = ipc_notify_connect(); + /* + * if still fails, try later + */ + if (fd < 0) { + sleep(1); + continue; + } + + ret = ipc_notify_receive(&fd, &msg); + if (ret != sizeof(msg)) + return NULL; + + if (strlen(msg.data.notify.msg) != 0) { struct mg_mgr *mgr = (struct mg_mgr *) data; char text[4096]; char str[4160]; - snescape(text, sizeof(text), msg.data.status.desc); + snescape(text, sizeof(text), msg.data.notify.msg); snprintf(str, sizeof(str), - "{\r\n" - "\t\"type\": \"message\",\r\n" - "\t\"level\": \"%d\",\r\n" - "\t\"text\": \"%s\"\r\n" - "}\r\n", - (msg.data.status.error) ? 3 : 6, /* RFC 5424 */ - text); + "{\r\n" + "\t\"type\": \"message\",\r\n" + "\t\"level\": \"%d\",\r\n" + "\t\"text\": \"%s\"\r\n" + "}\r\n", + msg.data.notify.level, /* RFC 5424 */ + text); broadcast(mgr, str); - continue; } - - usleep(50 * 1000); } return NULL;