From patchwork Sun Aug 15 03:46:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 1516894 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::938; helo=mail-ua1-x938.google.com; envelope-from=swupdate+bncbcl4hcw73qcbbpu44keamgqeqg5qwnq@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=qCDK3T6D; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=m8nRgm5t; dkim-atps=neutral Received: from mail-ua1-x938.google.com (mail-ua1-x938.google.com [IPv6:2607:f8b0:4864:20::938]) (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 4GnNXN2zTFz9sT6 for ; Sun, 15 Aug 2021 13:47:14 +1000 (AEST) Received: by mail-ua1-x938.google.com with SMTP id p4-20020ab03b84000000b002ab9500506fsf2172307uaw.13 for ; Sat, 14 Aug 2021 20:47:14 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1628999230; cv=pass; d=google.com; s=arc-20160816; b=UWVyVBveiCuy7+Z2/W7mSHM9N8i9nX75BvK8h2U6YBZw9Oc3h+LknppH9m8s2SOX7R gYSOxv9HpybRnS2fl8ZjdIH6ta2GbPXDfQpIfcUwGoGyjs2mM2wynFQzr4MRO2a1VKmp aVDv5NN2MT2Gr5ccxkTyf1AjY6w+l31vhw6Ixig7crRX+AbyivaTf3OA2FV+08NKaIEN /FFPdlQCBfXY8raLpYKKK7R0Dy1VPiHhIoq2nfd0qcLMs6caKs78ucfpZB4zlQzK3Icx trJyP5QRd9qs+xjPElpJYTsirk/ZZcho8Af+tf2YLXOWOkfcGusIXt1oSpEXBSXe06f3 cWGQ== 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=AKruRnnOK41pWkFaJOiaB+j+dd+rNpRvE4FgtKbeaBg=; b=S1C5LVJ360QYfkGdDpdoaP3HI85smkVvKJJldPazueOadULVucZc/SCJvgG1OLmonZ Bu3fMW4Eh9uOWctjaBF4JtRsHV7JnE/GXaTIWRdif/cJQRRdPZ3HRiMGuaszXZehg1kD YuZQifOBDPYhYJqRl+EApfoE6RZ7QeDAUAmzU2gCZHAQE9sHNuMg24iAQKGiFOcO2Var wXXHI5PoSQyCPxZTd49J0NedrOkS74dEY5Taf5JJ+2Hckjsbt6CyuseXde3BEsf/Y860 9vL8HL54Fcjo9KrJHDytOCvW9za5UEWgPCrE90a/G3XfdBqzzN4h8Fd1g7CxDSl/tLDM rA1A== ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=MGGpHc8L; spf=pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::32d 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=AKruRnnOK41pWkFaJOiaB+j+dd+rNpRvE4FgtKbeaBg=; b=qCDK3T6DzbuC57k76q5aRSZ6rqxrfk98QS+OyHTA3Qn5bQYQKcmKnUqPaPiVz+07Ok kiUflhc76+yYxW716vEblelqpU2a3Um0XRkv+uqSaQCm497Xza+V8t1AVhS0Dpdqxv+o vKLM7xqSA2hP3IcbliINVCOsAbAY7Yxxajx9FKlKzK243O6tLbbyaBF6mh6OJDIVNtmu fZQZh4gF+hhvd88PIqWGgnwx0Rdy0NweLleb+JanKllaXOgaXsA+4BlM4ZktwnndgJBa ije8xV6eqB+QNWUyo0px51q47PZ9/+/39B+vwwwRD2MSikzdxssq58w6aqEAIaf06QPQ NsYQ== 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=AKruRnnOK41pWkFaJOiaB+j+dd+rNpRvE4FgtKbeaBg=; b=m8nRgm5tdZ+jCk+vARiQPM0cL2jko5ayWqI2lq0Qs2zdPiHQroHd5XH7A26tP9sF2k qh8frwZrBIH+MRaKNGKqb664fyLNMzIVP4h4R7YjoWE2tgZJNpUVFlcS/6KV7ug2dwhP +Gf9ry/DO1U6nLPgqVWpC1gGm0Z9BNbAPBoZrykW3GuH0Puh2Q6vRbZCxq0LesiCdatw pD0ttLXS+DNBkOrqfdI3i7INodBlMrqOr9HYl8K5P5G0tAsPnqUM3G6oAVFQi1lA5dKo etgUsGU8rpuRvFAcT1VIpwA+uJ620FZUkYYJYDbmvgXV0tYMdWiw9lNkaMI8ln5YHfBg MSwA== 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=AKruRnnOK41pWkFaJOiaB+j+dd+rNpRvE4FgtKbeaBg=; b=a92qE7UERACwaqvmxPSkPKxh7C4FFnYAeu9Ip1OuVa3IQb4tkBbygYkQvjfC2zbfKW L5juGO0LsMtT1Oji+/9WH3DqUOShthsNiavbEmgje/P2yglT/1sb7v59i+/Jdx0z5T1j r/hquweyYAooCQoNrU5NdIy5cF1coaWc0vV2wQNr7yTo5Xl1ejBC4GpE/yjCd0xpA+Xk Vy7EOLkx830iIDayEFXyFsh+5YoeWv/CRxazZxExFgS5TGNKLHk38M1ALsDBNXXcH1k9 4GhhmMXFMXgpN9hKU7RLHsHhaAAS0hVXOlmIG+v89Z1nN7OEeW15FAHcszNSupiOMj9F mSIw== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM5300cqEfx+KgiKgiiFk29cWRnwJ/A1L66fzg3bi88uR4p8wZ+0HH cAwNT0UN46yF7vKaKiVDqLE= X-Google-Smtp-Source: ABdhPJzm5J3ZufxMHrQlJCyVQdMg1jHVsP8/05BKha79gCcJ1afUHqUMtGQzuG5HYEVApkebz3a3Ug== X-Received: by 2002:a67:eec3:: with SMTP id o3mr7062927vsp.33.1628999230580; Sat, 14 Aug 2021 20:47:10 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a1f:a1c4:: with SMTP id k187ls354830vke.8.gmail; Sat, 14 Aug 2021 20:47:10 -0700 (PDT) X-Received: by 2002:a1f:9657:: with SMTP id y84mr6236498vkd.6.1628999230037; Sat, 14 Aug 2021 20:47:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1628999230; cv=none; d=google.com; s=arc-20160816; b=EZFd/6EjyV2es0hXT20Vfsp9YhRnsbNwM1GQdzFlXEu9A4FWqP17VMwh5v1nnEGrIt 2z7bDe8EvIxEF3V9g2pnIofCxHvPM9sXT0rSWI/y0MRsIYVzEmsPqVi02Hln4iKyrS82 SCMgv3hqaCVKwXRKyklOkKjAQUHn6ZvJ5aTyvwSWxbysqHnqwRutVLaClaravWRTX4Ky extGaH0hXSMsntj6XpVY55NpJJZfcI5FV7QTFkw1r2sRgs8BdUWVbF+rG7twkODX9unP yeYwiH1Ys6MKDwDKVEGfEJsBelouvIgpzegrjdlPny/ymG0ejxSvyTqEKFfK69KI0V8R YGVA== 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=V1V60WZ+0CfAL3sUUWeT9FCmC4xsCKft8lijrX9kb0Y=; b=Q2HFaMaxoJ4b+HgxGuOSCn48gBEIIpmnqtaDUvV3vCVcTvo4qa+ADzIDXJFTBkbAks FXSi88b3886EmMt7YsCQSVsxTnWg710SAbdw+97VZCoxQwSC7V6MPO78pgM6MvmRIG+w 1hR1o7EGZdXU/nrrB+UytPp9C8PGulT6uS17f3CfvwyU5/qWW175tkAFPz3HUHONPt60 OU9/0k1P6U2dFLPGYO2yp797MbE/+EfpbPi4FcBEDpIVuQI5E/STnfjLugZz0HBKSEaw HlduJbg0Etn0ZXJWotN0wyx1POukp1ioVrJW1zQjI7BojXTAbc2royXgrmzCMGHwSz9l 4UCQ== ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=MGGpHc8L; spf=pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::32d as permitted sender) smtp.mailfrom=james.hilliard1@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from mail-ot1-x32d.google.com (mail-ot1-x32d.google.com. [2607:f8b0:4864:20::32d]) by gmr-mx.google.com with ESMTPS id m15si1267uab.1.2021.08.14.20.47.10 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 14 Aug 2021 20:47:10 -0700 (PDT) Received-SPF: pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::32d as permitted sender) client-ip=2607:f8b0:4864:20::32d; Received: by mail-ot1-x32d.google.com with SMTP id e13-20020a9d63cd0000b02904fa42f9d275so17032487otl.1 for ; Sat, 14 Aug 2021 20:47:10 -0700 (PDT) X-Received: by 2002:a9d:447:: with SMTP id 65mr8083154otc.197.1628999229211; Sat, 14 Aug 2021 20:47:09 -0700 (PDT) Received: from localhost.localdomain (97-118-242-196.hlrn.qwest.net. [97.118.242.196]) by smtp.gmail.com with ESMTPSA id bf41sm1324175oib.41.2021.08.14.20.47.08 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 14 Aug 2021 20:47:08 -0700 (PDT) From: James Hilliard To: swupdate@googlegroups.com Cc: James Hilliard Subject: [swupdate] [PATCH 1/1] IPC: add dedicated status socket interface Date: Sat, 14 Aug 2021 21:46:58 -0600 Message-Id: <20210815034658.24176-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=MGGpHc8L; spf=pass (google.com: domain of james.hilliard1@gmail.com designates 2607:f8b0:4864:20::32d 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: , Currently the only way to get status messages is by calling the ctrl IPC interface, however this has the disadvantage of only effectively allowing a single client at a time to read status messages as they are deleted when read using this interface. In order to allow multiple clients to read status messages add a dedicated interface for those messages similar to the progress interface. Signed-off-by: James Hilliard --- Kconfig | 5 + core/Makefile | 1 + core/network_thread.c | 10 -- core/notifier.c | 14 +++ core/status_thread.c | 176 ++++++++++++++++++++++++++++++++++ core/swupdate.c | 3 + core/util.c | 10 ++ include/status.h | 23 +++++ include/status_ipc.h | 53 ++++++++++ include/util.h | 1 + ipc/Makefile | 2 +- ipc/status_ipc.c | 94 ++++++++++++++++++ mongoose/mongoose_interface.c | 42 +++++--- 13 files changed, 409 insertions(+), 25 deletions(-) create mode 100644 core/status_thread.c create mode 100644 include/status.h create mode 100644 include/status_ipc.h create mode 100644 ipc/status_ipc.c diff --git a/Kconfig b/Kconfig index dc86957..7fc7382 100644 --- a/Kconfig +++ b/Kconfig @@ -215,6 +215,11 @@ config SOCKET_PROGRESS_PATH help Path to the socket progress information is sent to. +config SOCKET_STATUS_PATH + string "SWUpdate status socket path" + help + Path to the socket status information is sent to. + config SOCKET_NOTIFIER_DIRECTORY string "SWUpdate notifier socket directory" depends on HAVE_FREEBSD diff --git a/core/Makefile b/core/Makefile index fa30e6e..e6aeba4 100644 --- a/core/Makefile +++ b/core/Makefile @@ -22,6 +22,7 @@ obj-y += swupdate.o \ network_thread.o \ stream_interface.o \ progress_thread.o \ + status_thread.o \ parsing_library.o \ artifacts_versions.o \ swupdate_dict.o \ diff --git a/core/network_thread.c b/core/network_thread.c index adaf21c..59f1c15 100644 --- a/core/network_thread.c +++ b/core/network_thread.c @@ -106,16 +106,6 @@ static bool is_selection_allowed(const char *software_set, char *running_mode, return allowed; } -static void clean_msg(char *msg, char drop) -{ - char *lfpos; - lfpos = strchr(msg, drop); - while (lfpos) { - *lfpos = ' '; - lfpos = strchr(msg, drop); - } -} - static void network_notifier(RECOVERY_STATUS status, int error, int level, const char *msg) { int len = msg ? strlen(msg) : 0; diff --git a/core/notifier.c b/core/notifier.c index 810769c..7510f93 100644 --- a/core/notifier.c +++ b/core/notifier.c @@ -21,6 +21,7 @@ #include "util.h" #include "pctl.h" #include "progress.h" +#include "status.h" #ifdef CONFIG_SYSTEMD #include @@ -357,6 +358,18 @@ static void progress_notifier (RECOVERY_STATUS status, int event, int level, con swupdate_progress_info(status, event, msg); } +/* + * Status notifier: the message should be forwarded to the status + * interface only. + */ +static void status_notifier (RECOVERY_STATUS status, int event, int level, const char *msg) +{ + if (status == PROGRESS || event == RECOVERY_DWL) + return; + + swupdate_status_info(status, event, level, msg); +} + #if defined(__FreeBSD__) static char* socket_path = NULL; @@ -526,6 +539,7 @@ void notify_init(void) register_notifier(console_notifier); register_notifier(process_notifier); register_notifier(progress_notifier); + register_notifier(status_notifier); start_thread(notifier_thread, NULL); } } diff --git a/core/status_thread.c b/core/status_thread.c new file mode 100644 index 0000000..e950144 --- /dev/null +++ b/core/status_thread.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2016 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "swupdate.h" +#include +#include "util.h" +#include "pctl.h" +#include "network_ipc.h" +#include "network_interface.h" +#include +#include "generated/autoconf.h" + +#ifdef CONFIG_SYSTEMD +#include +#endif + +struct status_conn { + SIMPLEQ_ENTRY(status_conn) next; + int sockfd; +}; + +SIMPLEQ_HEAD(connections, status_conn); + +/* + * Structure contains data regarding + * current installation + */ +struct swupdate_status { + struct status_msg msg; + char *current_image; + const handler *curhnd; + struct connections conns; + pthread_mutex_t lock; + bool step_running; +}; +static struct swupdate_status notification; + +/* + * This must be called after acquiring the mutex + * for the status structure + */ +static void send_status_msg(void) +{ + struct status_conn *conn, *tmp; + struct swupdate_status *nmsg = ¬ification; + void *buf; + size_t count; + ssize_t n; + + SIMPLEQ_FOREACH_SAFE(conn, &nmsg->conns, next, tmp) { + buf = &nmsg->msg; + count = sizeof(nmsg->msg); + while (count > 0) { + n = send(conn->sockfd, buf, count, MSG_NOSIGNAL); + if (n <= 0) { + if (n == 0) { + TRACE("A status client is not responding, removing it."); + } else { + TRACE("A status client disappeared, removing it: %s", strerror(errno)); + } + close(conn->sockfd); + SIMPLEQ_REMOVE(&nmsg->conns, conn, + status_conn, next); + free(conn); + break; + } + count -= (size_t)n; + buf = (char*)buf + n; + } + } +} + +void swupdate_status_info(RECOVERY_STATUS status, int error, int level, const char *msg) +{ + struct swupdate_status *nmsg = ¬ification; + pthread_mutex_lock(&nmsg->lock); + memset(&nmsg->msg, 0, sizeof(nmsg->msg)); + if (msg) { + strncpy(nmsg->msg.desc, msg, + sizeof(nmsg->msg.desc) - 1); + clean_msg(nmsg->msg.desc, '\t'); + clean_msg(nmsg->msg.desc, '\n'); + clean_msg(nmsg->msg.desc, '\r'); + } + nmsg->msg.current = status; + nmsg->msg.level = level; + nmsg->msg.error = error; + nmsg->msg.desclen = strlen(nmsg->msg.desc); + send_status_msg(); + pthread_mutex_unlock(&nmsg->lock); +} + +static void unlink_socket(void) +{ +#ifdef CONFIG_SYSTEMD + if (sd_booted() && sd_listen_fds(0) > 0) { + /* + * There were socket fds handed-over by systemd, + * so don't delete the socket file. + */ + return; + } +#endif + unlink(get_status_socket()); +} + +void *status_thread (void __attribute__ ((__unused__)) *data) +{ + int listen, connfd; + socklen_t clilen; + struct sockaddr_un cliaddr; + struct swupdate_status *nmsg = ¬ification; + struct status_conn *conn; + + pthread_mutex_init(&nmsg->lock, NULL); + SIMPLEQ_INIT(&nmsg->conns); + + /* Initialize and bind to UDS */ + listen = listener_create(get_status_socket(), SOCK_STREAM); + if (listen < 0 ) { + ERROR("Error creating IPC socket %s, exiting.", get_status_socket()); + exit(2); + } + + if (atexit(unlink_socket) != 0) { + TRACE("Cannot setup socket cleanup on exit, %s won't be unlinked.", + get_status_socket()); + } + + thread_ready(); + do { + clilen = sizeof(cliaddr); + if ( (connfd = accept(listen, (struct sockaddr *) &cliaddr, &clilen)) < 0) { + if (errno == EINTR) + continue; + else { + TRACE("Accept returns: %s", strerror(errno)); + continue; + } + } + + /* + * Save the new connection to be handled by the status thread + */ + conn = (struct status_conn *)calloc(1, sizeof(*conn)); + if (!conn) { + ERROR("Out of memory, skipping..."); + continue; + } + conn->sockfd = connfd; + pthread_mutex_lock(&nmsg->lock); + SIMPLEQ_INSERT_TAIL(&nmsg->conns, conn, next); + pthread_mutex_unlock(&nmsg->lock); + } while(1); +} diff --git a/core/swupdate.c b/core/swupdate.c index 949a647..fe0b92b 100644 --- a/core/swupdate.c +++ b/core/swupdate.c @@ -43,6 +43,7 @@ #include "sslapi.h" #include "suricatta/suricatta.h" #include "progress.h" +#include "status.h" #include "parselib.h" #include "swupdate_settings.h" #include "pctl.h" @@ -860,6 +861,8 @@ int main(int argc, char **argv) start_thread(progress_bar_thread, NULL); + start_thread(status_thread, NULL); + /* wait for threads to be done before starting children */ wait_threads_ready(); diff --git a/core/util.c b/core/util.c index 6188650..e54d156 100644 --- a/core/util.c +++ b/core/util.c @@ -1137,3 +1137,13 @@ bool img_check_free_space(struct img_type *img, int fd) return check_free_space(fd, size, img->fname); } + +void clean_msg(char *msg, char drop) +{ + char *lfpos; + lfpos = strchr(msg, drop); + while (lfpos) { + *lfpos = ' '; + lfpos = strchr(msg, drop); + } +} diff --git a/include/status.h b/include/status.h new file mode 100644 index 0000000..a22a8f5 --- /dev/null +++ b/include/status.h @@ -0,0 +1,23 @@ +/* + * (C) Copyright 2016 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef _INSTALL_STATUS_H +#define _INSTALL_STATUS_H + +#include +#include + +/* + * Internal SWUpdate functions to drive the status + * interface. Common status definitions for internal + * as well as external use are defined in status_ipc.h + */ +void swupdate_status_info(RECOVERY_STATUS status, int event, int level, const char *msg); + +void *status_thread (void *data); + +#endif diff --git a/include/status_ipc.h b/include/status_ipc.h new file mode 100644 index 0000000..fcf70d4 --- /dev/null +++ b/include/status_ipc.h @@ -0,0 +1,53 @@ +/* + * Author: Christian Storm + * Copyright (C) 2017, Siemens AG + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef _STATUS_IPC_H +#define _STATUS_IPC_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PRDESCSIZE 2048 + +extern char* SOCKET_STATUS_PATH; + +/* + * Message sent via status socket. + * Data is sent in LE if required. + */ +struct status_msg { + unsigned int magic; /* Magic Number */ + int current; + int level; + int error; + unsigned int desclen; /* Len of data valid in desc */ + char desc[PRDESCSIZE]; /* additional information about install */ +}; + +char *get_status_socket(void); + +/* Standard function to connect to status interface */ +int status_ipc_connect(bool reconnect); + +/* + * In case more as an instance of SWUpdate is running, this allows to select + * which should be taken + */ +int status_ipc_connect_with_path(const char *socketpath, bool reconnect); + +/* Retrieve messages from status interface (it blocks) */ +int status_ipc_receive(int *connfd, struct status_msg *msg); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/include/util.h b/include/util.h index 9f29f5f..0086694 100644 --- a/include/util.h +++ b/include/util.h @@ -220,6 +220,7 @@ int read_lines_notify(int fd, char *buf, int buf_size, int *buf_offset, LOGLEVEL level); long long get_output_size(struct img_type *img, bool strict); bool img_check_free_space(struct img_type *img, int fd); +void clean_msg(char *msg, char drop); /* Decryption key functions */ int load_decryption_key(char *fname); diff --git a/ipc/Makefile b/ipc/Makefile index 71a1f42..661e214 100644 --- a/ipc/Makefile +++ b/ipc/Makefile @@ -1,6 +1,6 @@ # Copyright (C) 2014-2018 Stefano Babic # # SPDX-License-Identifier: GPL-2.0-only -obj-y += network_ipc.o network_ipc-if.o progress_ipc.o +obj-y += network_ipc.o network_ipc-if.o progress_ipc.o status_ipc.o EXTRA_CFLAGS += -fPIC diff --git a/ipc/status_ipc.c b/ipc/status_ipc.c new file mode 100644 index 0000000..4d95aee --- /dev/null +++ b/ipc/status_ipc.c @@ -0,0 +1,94 @@ +/* + * Author: Christian Storm + * Copyright (C) 2017, Siemens AG + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef CONFIG_SOCKET_STATUS_PATH +char *SOCKET_STATUS_PATH = (char*)CONFIG_SOCKET_STATUS_PATH; +#else +char *SOCKET_STATUS_PATH = NULL; +#endif + +#define SOCKET_STATUS_DEFAULT "swupdatestatus" + +char *get_status_socket(void) { + if (!SOCKET_STATUS_PATH || !strlen(SOCKET_STATUS_PATH)) { + const char *tmpdir = getenv("TMPDIR"); + if (!tmpdir) + tmpdir = "/tmp"; + + if (asprintf(&SOCKET_STATUS_PATH, "%s/%s", tmpdir, SOCKET_STATUS_DEFAULT) == -1) + return (char *)"/tmp/"SOCKET_STATUS_DEFAULT; + } + + return SOCKET_STATUS_PATH; +} + +static int _status_ipc_connect(const char *socketpath, bool reconnect) +{ + struct sockaddr_un servaddr; + int fd = socket(AF_LOCAL, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sun_family = AF_LOCAL; + strncpy(servaddr.sun_path, socketpath, sizeof(servaddr.sun_path) - 1); + + /* + * Check to get a valid socket + */ + if (fd < 0) + return -1; + + do { + if (connect(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == 0) { + break; + } + if (!reconnect) { + fprintf(stderr, "cannot communicate with SWUpdate via %s\n", socketpath); + close(fd); + return -1; + } + + usleep(10000); + } while (true); + + fprintf(stdout, "Connected to SWUpdate via %s\n", socketpath); + return fd; +} + +int status_ipc_connect_with_path(const char *socketpath, bool reconnect) { + return _status_ipc_connect(socketpath, reconnect); +} + +int status_ipc_connect(bool reconnect) +{ + return _status_ipc_connect(get_status_socket(), reconnect); +} + +int status_ipc_receive(int *connfd, struct status_msg *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; + } + + return ret; +} diff --git a/mongoose/mongoose_interface.c b/mongoose/mongoose_interface.c index 2e9416b..350b06e 100644 --- a/mongoose/mongoose_interface.c +++ b/mongoose/mongoose_interface.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -141,31 +142,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); + struct status_msg msg; + int ret; - if (!ret && strlen(msg.data.status.desc) != 0) { + if (fd < 0) + fd = status_ipc_connect(true); + /* + * if still fails, try later + */ + if (fd < 0) { + sleep(1); + continue; + } + + ret = status_ipc_receive(&fd, &msg); + if (ret != sizeof(msg)) + return NULL; + + if (msg.desclen != 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.desc); 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.level, /* RFC 5424 */ + text); broadcast(mgr, str); - continue; } - - usleep(50 * 1000); } return NULL;