diff options
Diffstat (limited to 'legacy')
200 files changed, 20913 insertions, 7231 deletions
diff --git a/legacy/busybox/0001-ash-add-support-for-command_not_found_handle-hook-fu.patch b/legacy/busybox/0001-ash-add-support-for-command_not_found_handle-hook-fu.patch deleted file mode 100644 index 929370b9d..000000000 --- a/legacy/busybox/0001-ash-add-support-for-command_not_found_handle-hook-fu.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 185ba65457e991ebd0f6e64266380df5e11cc489 Mon Sep 17 00:00:00 2001 -From: William Pitcock <nenolod@dereferenced.org> -Date: Thu, 19 Oct 2017 17:24:40 +0000 -Subject: [PATCH 01/16] ash: add support for command_not_found_handle hook - function, like bash - -This implements support for the command_not_found_handle hook function, which is -useful for allowing package managers to suggest packages which could provide the -command. - -Unlike bash, however, we ignore exit codes from the hook function and always return -the correct POSIX error code (EX_NOTFOUND). - -Signed-off-by: William Pitcock <nenolod@dereferenced.org> ---- - shell/ash.c | 24 ++++++++++++++++++++++-- - 1 file changed, 22 insertions(+), 2 deletions(-) - -diff --git a/shell/ash.c b/shell/ash.c -index b73a79975..7ceb91920 100644 ---- a/shell/ash.c -+++ b/shell/ash.c -@@ -132,6 +132,15 @@ - //config: you to run the specified command or builtin, - //config: even when there is a function with the same name. - //config: -+//config:config ASH_COMMAND_NOT_FOUND_HOOK -+//config: bool "command_not_found_handle hook support" -+//config: default y -+//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -+//config: help -+//config: Enable support for the 'command_not_found_handle' hook function, -+//config: from GNU bash, which allows for alternative command not found -+//config: handling. -+//config: - //config:endif # ash options - - //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) -@@ -13166,8 +13175,19 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) - /* We failed. If there was an entry for this command, delete it */ - if (cmdp && updatetbl) - delete_cmd_entry(); -- if (act & DO_ERR) -- ash_msg("%s: %s", name, errmsg(e, "not found")); -+ if (act & DO_ERR) { -+#ifdef CONFIG_ASH_COMMAND_NOT_FOUND_HOOK -+#define HOOKFN_NAME "command_not_found_handle" -+ char hookfn_name[] = HOOKFN_NAME; -+ struct tblentry *hookp = cmdlookup(hookfn_name, 0); -+ if (hookp != NULL && hookp->cmdtype == CMDFUNCTION) { -+ evalfun(hookp->param.func, 2, (char *[]){ hookfn_name, name }, 0); -+ entry->cmdtype = CMDUNKNOWN; -+ return; -+ } else -+#endif -+ ash_msg("%s: %s", name, errmsg(e, "not found")); -+ } - entry->cmdtype = CMDUNKNOWN; - return; - --- -2.16.2 - diff --git a/legacy/busybox/0001-ash-exec-busybox.static.patch b/legacy/busybox/0001-ash-exec-busybox.static.patch deleted file mode 100644 index fdf134960..000000000 --- a/legacy/busybox/0001-ash-exec-busybox.static.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 134582e8dd1c85cbcf1fc047956a57fcd642e46a Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 4 Aug 2016 11:03:07 +0200 -Subject: [PATCH 01/11] ash: exec busybox.static - ---- - shell/ash.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/shell/ash.c b/shell/ash.c -index b7635a823..e613ee6bb 100644 ---- a/shell/ash.c -+++ b/shell/ash.c -@@ -7721,6 +7721,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** - } - /* re-exec ourselves with the new arguments */ - execve(bb_busybox_exec_path, argv, envp); -+ execve("/bin/busybox.static",argv,envp); -+ execve("/bin/busybox",argv,envp); - /* If they called chroot or otherwise made the binary no longer - * executable, fall through */ - } --- -2.13.2 - diff --git a/legacy/busybox/0001-cat-fix-cat-e-and-cat-v-erroneously-numbering-1st-li.patch b/legacy/busybox/0001-cat-fix-cat-e-and-cat-v-erroneously-numbering-1st-li.patch deleted file mode 100644 index 4680b920e..000000000 --- a/legacy/busybox/0001-cat-fix-cat-e-and-cat-v-erroneously-numbering-1st-li.patch +++ /dev/null @@ -1,63 +0,0 @@ -From d80eecb86812c1fbda652f9b995060c26ba0b155 Mon Sep 17 00:00:00 2001 -From: Denys Vlasenko <vda.linux@googlemail.com> -Date: Sun, 29 Apr 2018 14:05:43 +0200 -Subject: [PATCH] cat: fix cat -e and cat -v erroneously numbering 1st line - -function old new delta -cat_main 418 421 +3 - -Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> ---- - coreutils/cat.c | 6 +++--- - testsuite/cat.tests | 21 +++++++++++++++++++++ - 2 files changed, 24 insertions(+), 3 deletions(-) - create mode 100755 testsuite/cat.tests - -diff --git a/coreutils/cat.c b/coreutils/cat.c -index 5f02233ca..fb735f994 100644 ---- a/coreutils/cat.c -+++ b/coreutils/cat.c -@@ -112,10 +112,10 @@ static int catv(unsigned opts, char **argv) - int retval = EXIT_SUCCESS; - int fd; - #if ENABLE_FEATURE_CATN -- unsigned lineno = 0; -- unsigned eol_char = (opts & (CAT_OPT_n|CAT_OPT_b)) ? '\n' : 0x100; -+ bool eol_seen = (opts & (CAT_OPT_n|CAT_OPT_b)); -+ unsigned eol_char = (eol_seen ? '\n' : 0x100); - unsigned skip_num_on = (opts & CAT_OPT_b) ? '\n' : 0x100; -- bool eol_seen = 1; -+ unsigned lineno = 0; - #endif - - BUILD_BUG_ON(CAT_OPT_e != VISIBLE_ENDLINE); -diff --git a/testsuite/cat.tests b/testsuite/cat.tests -new file mode 100755 -index 000000000..404ebedeb ---- /dev/null -+++ b/testsuite/cat.tests -@@ -0,0 +1,21 @@ -+#!/bin/sh -+ -+# Copyright 2018 by Denys Vlasenko <vda.linux@googlemail.com> -+# Licensed under GPLv2, see file LICENSE in this source tree. -+ -+. ./testing.sh -+ -+# testing "description" "command" "result" "infile" "stdin" -+testing 'cat -e' \ -+ 'cat -e' \ -+ 'foo$\n' \ -+ '' \ -+ 'foo\n' -+ -+testing 'cat -v' \ -+ 'cat -v' \ -+ 'foo\n' \ -+ '' \ -+ 'foo\n' -+ -+exit $FAILCOUNT --- -2.17.0 - diff --git a/legacy/busybox/0001-wget-emit-a-message-that-certificate-verification-is.patch b/legacy/busybox/0001-wget-emit-a-message-that-certificate-verification-is.patch deleted file mode 100644 index 3780b039e..000000000 --- a/legacy/busybox/0001-wget-emit-a-message-that-certificate-verification-is.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 948090c675f8b60b74c7357fcafb1cc8c179e0a6 Mon Sep 17 00:00:00 2001 -From: Denys Vlasenko <vda.linux@googlemail.com> -Date: Mon, 28 May 2018 14:36:26 +0200 -Subject: [PATCH] wget: emit a message that certificate verification is not - implemented - -function old new delta -spawn_ssl_client 185 209 +24 - -Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> ---- - networking/wget.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/networking/wget.c b/networking/wget.c -index d1d85230c..cd92b3a28 100644 ---- a/networking/wget.c -+++ b/networking/wget.c -@@ -136,6 +136,7 @@ - //usage: "Retrieve files via HTTP or FTP\n" - //usage: IF_FEATURE_WGET_LONG_OPTIONS( - //usage: "\n --spider Only check URL existence: $? is 0 if exists" -+///////: "\n --no-check-certificate Don't validate the server's certificate" - //usage: ) - //usage: "\n -c Continue retrieval of aborted transfer" - //usage: "\n -q Quiet" -@@ -267,6 +268,7 @@ enum { - WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, -+ WGET_OPT_NO_CHECK_CERT = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - }; - - enum { -@@ -765,6 +767,9 @@ static void spawn_ssl_client(const char *host, int network_fd) - int pid; - char *servername, *p; - -+ if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) -+ bb_error_msg("note: TLS certificate validation not implemented"); -+ - servername = xstrdup(host); - p = strrchr(servername, ':'); - if (p) *p = '\0'; -@@ -1353,10 +1358,9 @@ IF_DESKTOP( "tries\0" Required_argument "t") - "header\0" Required_argument "\xff" - "post-data\0" Required_argument "\xfe" - "spider\0" No_argument "\xfd" -+ "no-check-certificate\0" No_argument "\xfc" - /* Ignored (we always use PASV): */ - IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") -- /* Ignored (we don't do ssl) */ --IF_DESKTOP( "no-check-certificate\0" No_argument "\xf0") - /* Ignored (we don't support caching) */ - IF_DESKTOP( "no-cache\0" No_argument "\xf0") - IF_DESKTOP( "no-verbose\0" No_argument "\xf0") -@@ -1416,6 +1420,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") - if (option_mask32 & WGET_OPT_HEADER) bb_error_msg("--header"); - if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); - if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); -+ if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate"); - exit(0); - #endif - argv += optind; --- -2.17.0 - diff --git a/legacy/busybox/0002-app-location-for-cpio-vi-and-lspci.patch b/legacy/busybox/0002-app-location-for-cpio-vi-and-lspci.patch deleted file mode 100644 index 8c8e4ee7a..000000000 --- a/legacy/busybox/0002-app-location-for-cpio-vi-and-lspci.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 8937e2dfb3dbfa23597853e9605f930b3607fa63 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Tue, 27 Dec 2016 20:46:59 +0100 -Subject: [PATCH 02/11] app location for cpio, vi and lspci - -Adjust location to where alpine linux installs them ---- - archival/cpio.c | 2 +- - editors/vi.c | 2 +- - util-linux/lspci.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/archival/cpio.c b/archival/cpio.c -index 683f0bb1f..45362b6bc 100644 ---- a/archival/cpio.c -+++ b/archival/cpio.c -@@ -43,7 +43,7 @@ - //config: help - //config: Passthrough mode. Rarely used. - --//applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP)) -+//applet:IF_CPIO(APPLET(cpio, BB_DIR_USR_BIN, BB_SUID_DROP)) - //kbuild:lib-$(CONFIG_CPIO) += cpio.o - - //usage:#define cpio_trivial_usage -diff --git a/editors/vi.c b/editors/vi.c -index 76d1f261b..73d0a67a9 100644 ---- a/editors/vi.c -+++ b/editors/vi.c -@@ -163,7 +163,7 @@ - //config: Unless you want more (or less) frequent "undo points" while typing, - //config: you should probably leave this unchanged. - --//applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) -+//applet:IF_VI(APPLET(vi, BB_DIR_USR_BIN, BB_SUID_DROP)) - - //kbuild:lib-$(CONFIG_VI) += vi.o - -diff --git a/util-linux/lspci.c b/util-linux/lspci.c -index 8b38a2366..f918f0972 100644 ---- a/util-linux/lspci.c -+++ b/util-linux/lspci.c -@@ -16,7 +16,7 @@ - //config: - //config: This version uses sysfs (/sys/bus/pci/devices) only. - --//applet:IF_LSPCI(APPLET(lspci, BB_DIR_USR_BIN, BB_SUID_DROP)) -+//applet:IF_LSPCI(APPLET(lspci, BB_DIR_USR_SBIN, BB_SUID_DROP)) - - //kbuild:lib-$(CONFIG_LSPCI) += lspci.o - --- -2.13.2 - diff --git a/legacy/busybox/0002-fsck-resolve-LABEL-.-UUID-.-spec-to-device.patch b/legacy/busybox/0002-fsck-resolve-LABEL-.-UUID-.-spec-to-device.patch deleted file mode 100644 index 72df8ecf9..000000000 --- a/legacy/busybox/0002-fsck-resolve-LABEL-.-UUID-.-spec-to-device.patch +++ /dev/null @@ -1,59 +0,0 @@ -From bce882404ab41d32d5d9def274e49264717135b2 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Tue, 28 Nov 2017 13:23:17 +0100 -Subject: [PATCH 02/16] fsck: resolve LABEL=.../UUID=... spec to device - ---- - e2fsprogs/fsck.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c -index 1c285bb92..5af38c0aa 100644 ---- a/e2fsprogs/fsck.c -+++ b/e2fsprogs/fsck.c -@@ -60,6 +60,7 @@ - //usage: "\n -t TYPE List of filesystem types to check" - - #include "libbb.h" -+#include "volume_id.h" - #include "common_bufsiz.h" - - /* "progress indicator" code is somewhat buggy and ext[23] specific. -@@ -523,12 +524,13 @@ static int wait_many(int flags) - * Execute a particular fsck program, and link it into the list of - * child processes we are waiting for. - */ --static void execute(const char *type, const char *device, -+static void execute(const char *type, const char *spec, - const char *mntpt /*, int interactive */) - { - int i; - struct fsck_instance *inst; - pid_t pid; -+ char *device = (char *)spec; - - G.args[0] = xasprintf("fsck.%s", type); - -@@ -543,7 +545,8 @@ static void execute(const char *type, const char *device, - } - #endif - -- G.args[G.num_args - 2] = (char*)device; -+ resolve_mount_spec(&device); -+ G.args[G.num_args - 2] = device; - /* G.args[G.num_args - 1] = NULL; - already is */ - - if (G.verbose || G.noexecute) { -@@ -972,9 +975,6 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) - - /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */ - if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) { --// FIXME: must check that arg is a blkdev, or resolve --// "/path", "UUID=xxx" or "LABEL=xxx" into block device name --// ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties) - devices = xrealloc_vector(devices, 2, num_devices); - devices[num_devices++] = arg; - continue; --- -2.16.2 - diff --git a/legacy/busybox/0003-ash-exec-busybox.static.patch b/legacy/busybox/0003-ash-exec-busybox.static.patch deleted file mode 100644 index 94239a2eb..000000000 --- a/legacy/busybox/0003-ash-exec-busybox.static.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 36b6cc36d1f259e4ac76a1c2de743113845ff4cd Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 4 Aug 2016 11:03:07 +0200 -Subject: [PATCH 03/16] ash: exec busybox.static - ---- - shell/ash.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/shell/ash.c b/shell/ash.c -index 7ceb91920..d04096a9b 100644 ---- a/shell/ash.c -+++ b/shell/ash.c -@@ -7845,6 +7845,8 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c - } - /* re-exec ourselves with the new arguments */ - execve(bb_busybox_exec_path, argv, envp); -+ execve("/bin/busybox.static",argv,envp); -+ execve("/bin/busybox",argv,envp); - /* If they called chroot or otherwise made the binary no longer - * executable, fall through */ - } --- -2.16.2 - diff --git a/legacy/busybox/0003-udhcpc-set-default-discover-retries-to-5.patch b/legacy/busybox/0003-udhcpc-set-default-discover-retries-to-5.patch deleted file mode 100644 index 5671ee1b0..000000000 --- a/legacy/busybox/0003-udhcpc-set-default-discover-retries-to-5.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 18415adc1cd9993a95d100dd773daf69b8ec819e Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 4 Aug 2016 11:08:35 +0200 -Subject: [PATCH 03/11] udhcpc: set default discover retries to 5 - -Some slower nics needs more attempts to get a lease ---- - networking/udhcp/dhcpc.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c -index 1a66c610e..43aac1b85 100644 ---- a/networking/udhcp/dhcpc.c -+++ b/networking/udhcp/dhcpc.c -@@ -1191,7 +1191,7 @@ static void client_background(void) - //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" - //usage: "\n -p,--pidfile FILE Create pidfile" - //usage: "\n -B,--broadcast Request broadcast replies" --//usage: "\n -t,--retries N Send up to N discover packets (default 3)" -+//usage: "\n -t,--retries N Send up to N discover packets (default 5)" - //usage: "\n -T,--timeout SEC Pause between packets (default 3)" - //usage: "\n -A,--tryagain SEC Wait if lease is not obtained (default 20)" - //usage: "\n -n,--now Exit if lease is not obtained" -@@ -1274,7 +1274,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) - llist_t *list_x = NULL; - int tryagain_timeout = 20; - int discover_timeout = 3; -- int discover_retries = 3; -+ int discover_retries = 5; - uint32_t server_addr = server_addr; /* for compiler */ - uint32_t requested_ip = 0; - uint32_t xid = xid; /* for compiler */ --- -2.13.2 - diff --git a/legacy/busybox/0004-app-location-for-cpio-vi-and-lspci.patch b/legacy/busybox/0004-app-location-for-cpio-vi-and-lspci.patch deleted file mode 100644 index 7f105cb67..000000000 --- a/legacy/busybox/0004-app-location-for-cpio-vi-and-lspci.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 9bbc93f12f7cff8fb51a0bf89907d9875f5c14e6 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Tue, 27 Dec 2016 20:46:59 +0100 -Subject: [PATCH 04/16] app location for cpio, vi and lspci - -Adjust location to where alpine linux installs them ---- - archival/cpio.c | 2 +- - editors/vi.c | 2 +- - util-linux/lspci.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/archival/cpio.c b/archival/cpio.c -index 1d6cbd1e2..0c14f79e7 100644 ---- a/archival/cpio.c -+++ b/archival/cpio.c -@@ -39,7 +39,7 @@ - //config: help - //config: Passthrough mode. Rarely used. - --//applet:IF_CPIO(APPLET(cpio, BB_DIR_BIN, BB_SUID_DROP)) -+//applet:IF_CPIO(APPLET(cpio, BB_DIR_USR_BIN, BB_SUID_DROP)) - - //kbuild:lib-$(CONFIG_CPIO) += cpio.o - -diff --git a/editors/vi.c b/editors/vi.c -index cdfb27cc5..20077727e 100644 ---- a/editors/vi.c -+++ b/editors/vi.c -@@ -161,7 +161,7 @@ - //config: Unless you want more (or less) frequent "undo points" while typing, - //config: you should probably leave this unchanged. - --//applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) -+//applet:IF_VI(APPLET(vi, BB_DIR_USR_BIN, BB_SUID_DROP)) - - //kbuild:lib-$(CONFIG_VI) += vi.o - -diff --git a/util-linux/lspci.c b/util-linux/lspci.c -index 0000fbfda..34189d2b5 100644 ---- a/util-linux/lspci.c -+++ b/util-linux/lspci.c -@@ -16,7 +16,7 @@ - //config: - //config: This version uses sysfs (/sys/bus/pci/devices) only. - --//applet:IF_LSPCI(APPLET_NOEXEC(lspci, lspci, BB_DIR_USR_BIN, BB_SUID_DROP, lspci)) -+//applet:IF_LSPCI(APPLET_NOEXEC(lspci, lspci, BB_DIR_USR_SBIN, BB_SUID_DROP, lspci)) - - //kbuild:lib-$(CONFIG_LSPCI) += lspci.o - --- -2.16.2 - diff --git a/legacy/busybox/0004-ping-make-ping-work-without-root-privileges.patch b/legacy/busybox/0004-ping-make-ping-work-without-root-privileges.patch deleted file mode 100644 index 77fa5ed76..000000000 --- a/legacy/busybox/0004-ping-make-ping-work-without-root-privileges.patch +++ /dev/null @@ -1,197 +0,0 @@ -From bef770d1ee4179e380dff24305d9b6d899147add Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Tue, 29 Mar 2016 18:59:22 +0200 -Subject: [PATCH 04/11] ping: make ping work without root privileges - ---- - networking/ping.c | 103 +++++++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 87 insertions(+), 16 deletions(-) - -diff --git a/networking/ping.c b/networking/ping.c -index 94fb007f5..26e40e1fc 100644 ---- a/networking/ping.c -+++ b/networking/ping.c -@@ -155,6 +155,7 @@ enum { - pingsock = 0, - }; - -+static int using_dgram; - static void - #if ENABLE_PING6 - create_icmp_socket(len_and_sockaddr *lsa) -@@ -171,9 +172,23 @@ create_icmp_socket(void) - #endif - sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */ - if (sock < 0) { -- if (errno == EPERM) -- bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); -- bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); -+ if (errno != EPERM) -+ bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); -+#if defined(__linux__) || defined(__APPLE__) -+ /* We don't have root privileges. Try SOCK_DGRAM instead. -+ * Linux needs net.ipv4.ping_group_range for this to work. -+ * MacOSX allows ICMP_ECHO, ICMP_TSTAMP or ICMP_MASKREQ -+ */ -+#if ENABLE_PING6 -+ if (lsa->u.sa.sa_family == AF_INET6) -+ sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); -+ else -+#endif -+ sock = socket(AF_INET, SOCK_DGRAM, 1); /* 1 == ICMP */ -+ if (sock < 0) -+#endif -+ bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); -+ using_dgram = 1; - } - - xmove_fd(sock, pingsock); -@@ -226,10 +241,12 @@ static void ping4(len_and_sockaddr *lsa) - bb_perror_msg("recvfrom"); - continue; - } -- if (c >= 76) { /* ip + icmp */ -- struct iphdr *iphdr = (struct iphdr *) G.packet; -+ if (c >= 76 || using_dgram && (c == 64)) { /* ip + icmp */ -+ if(!using_dgram) { -+ struct iphdr *iphdr = (struct iphdr *) G.packet; - -- pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ -+ pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ -+ } else pkt = (struct icmp *) G.packet; - if (pkt->icmp_id != G.myid) - continue; /* not our ping */ - if (pkt->icmp_type == ICMP_ECHOREPLY) -@@ -627,19 +644,21 @@ static void unpack_tail(int sz, uint32_t *tp, - } - static void unpack4(char *buf, int sz, struct sockaddr_in *from) - { -- struct icmp *icmppkt; - struct iphdr *iphdr; -+ struct icmp *icmppkt; - int hlen; - - /* discard if too short */ - if (sz < (datalen + ICMP_MINLEN)) - return; -+ if(!using_dgram) { -+ /* check IP header */ -+ iphdr = (struct iphdr *) buf; -+ hlen = iphdr->ihl << 2; -+ sz -= hlen; -+ icmppkt = (struct icmp *) (buf + hlen); -+ } else icmppkt = (struct icmp *) buf; - -- /* check IP header */ -- iphdr = (struct iphdr *) buf; -- hlen = iphdr->ihl << 2; -- sz -= hlen; -- icmppkt = (struct icmp *) (buf + hlen); - if (icmppkt->icmp_id != myid) - return; /* not our ping */ - -@@ -651,7 +670,7 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from) - tp = (uint32_t *) icmppkt->icmp_data; - unpack_tail(sz, tp, - inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), -- recv_seq, iphdr->ttl); -+ recv_seq, using_dgram ? 42 : iphdr->ttl); - } else if (icmppkt->icmp_type != ICMP_ECHO) { - bb_error_msg("warning: got ICMP %d (%s)", - icmppkt->icmp_type, -@@ -695,11 +714,31 @@ static void ping4(len_and_sockaddr *lsa) - int sockopt; - - pingaddr.sin = lsa->u.sin; -- if (source_lsa) { -+ if (source_lsa && !using_dgram) { - if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF, - &source_lsa->u.sa, source_lsa->len)) - bb_error_msg_and_die("can't set multicast source interface"); - xbind(pingsock, &source_lsa->u.sa, source_lsa->len); -+ } else if(using_dgram) { -+ struct sockaddr_in sa; -+ socklen_t sl; -+ -+ sa.sin_family = AF_INET; -+ sa.sin_port = 0; -+ sa.sin_addr.s_addr = source_lsa ? -+ source_lsa->u.sin.sin_addr.s_addr : 0; -+ sl = sizeof(sa); -+ -+ if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) { -+ perror("bind"); -+ exit(2); -+ } -+ -+ if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) { -+ perror("getsockname"); -+ exit(2); -+ } -+ myid = sa.sin_port; - } - - /* enable broadcast pings */ -@@ -716,6 +755,15 @@ static void ping4(len_and_sockaddr *lsa) - setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl); - } - -+ if(using_dgram) { -+ int hold = 65536; -+ if (setsockopt(pingsock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold))) -+ perror("WARNING: setsockopt(IP_RECVTTL)"); -+ if (setsockopt(pingsock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold))) -+ perror("WARNING: setsockopt(IP_RETOPTS)"); -+ -+ } -+ - signal(SIGINT, print_stats_and_exit); - - /* start the ping's going ... */ -@@ -749,10 +797,33 @@ static void ping6(len_and_sockaddr *lsa) - char control_buf[CMSG_SPACE(36)]; - - pingaddr.sin6 = lsa->u.sin6; -- if (source_lsa) -+ if (source_lsa && !using_dgram) - xbind(pingsock, &source_lsa->u.sa, source_lsa->len); -+ else if(using_dgram) { -+ struct sockaddr_in6 sa = {0}; -+ socklen_t sl; -+ -+ sa.sin6_family = AF_INET6; -+ sa.sin6_port = 0; -+ if(source_lsa) { -+ memcpy(&sa.sin6_addr, &source_lsa->u.sin6.sin6_addr, sizeof(struct in6_addr)); -+ } -+ sl = sizeof(sa); -+ -+ if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) { -+ perror("bind"); -+ exit(2); -+ } -+ -+ if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) { -+ perror("getsockname"); -+ exit(2); -+ } -+ myid = sa.sin6_port; -+ } - - #ifdef ICMP6_FILTER -+ if(!using_dgram) - { - struct icmp6_filter filt; - if (!(option_mask32 & OPT_VERBOSE)) { -@@ -880,7 +951,7 @@ static int common_ping_main(int opt, char **argv) - if (opt & OPT_p) - G.pattern = xstrtou_range(str_p, 16, 0, 255); - -- myid = (uint16_t) getpid(); -+ if (!using_dgram) myid = (uint16_t) getpid(); - hostname = argv[optind]; - #if ENABLE_PING6 - { --- -2.13.2 - diff --git a/legacy/busybox/0005-fbsplash-support-console-switching.patch b/legacy/busybox/0005-fbsplash-support-console-switching.patch deleted file mode 100644 index 792c2d6c8..000000000 --- a/legacy/busybox/0005-fbsplash-support-console-switching.patch +++ /dev/null @@ -1,187 +0,0 @@ -From a8f7d33f47cc28732cd04573ae1fb6a1ca6e9617 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Mon, 24 Sep 2012 07:58:29 +0300 -Subject: [PATCH 05/11] fbsplash: support console switching -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Timo Teräs <timo.teras@iki.fi> ---- - miscutils/fbsplash.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 76 insertions(+), 7 deletions(-) - -diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c -index fc6c9b953..ec5947314 100644 ---- a/miscutils/fbsplash.c -+++ b/miscutils/fbsplash.c -@@ -47,7 +47,7 @@ - //kbuild:lib-$(CONFIG_FBSPLASH) += fbsplash.o - - //usage:#define fbsplash_trivial_usage --//usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" -+//usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD] [-T tty]" - //usage:#define fbsplash_full_usage "\n\n" - //usage: " -s Image" - //usage: "\n -c Hide cursor" -@@ -57,11 +57,17 @@ - //usage: "\n BAR_R,BAR_G,BAR_B" - //usage: "\n -f Control pipe (else exit after drawing image)" - //usage: "\n commands: 'NN' (% for progress bar) or 'exit'" -+//usage: "\n -T Switch to TTY to hide all console messages" - - #include "libbb.h" - #include "common_bufsiz.h" - #include <linux/fb.h> - -+#include <sys/vt.h> -+#include <sys/ioctl.h> -+#include <linux/tiocl.h> -+#include <linux/kd.h> -+ - /* If you want logging messages on /tmp/fbsplash.log... */ - #define DEBUG 0 - -@@ -73,6 +79,8 @@ struct globals { - unsigned char *addr; // pointer to framebuffer memory - unsigned ns[7]; // n-parameters - const char *image_filename; -+ int silent_tty, fd_tty_s; -+ bool do_not_draw; - struct fb_var_screeninfo scr_var; - struct fb_fix_screeninfo scr_fix; - unsigned bytes_per_pixel; -@@ -483,6 +491,11 @@ static void init(const char *cfg_filename) - config_close(parser); - } - -+static void sighandler(int sig) -+{ -+ ioctl(G.fd_tty_s, VT_RELDISP, sig == SIGUSR1 ? 1 : 2); -+ G.do_not_draw = (sig != SIGUSR2); -+} - - int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int fbsplash_main(int argc UNUSED_PARAM, char **argv) -@@ -492,6 +505,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - char *num_buf; - unsigned num; - bool bCursorOff; -+ int fd_tty0, active_vt; -+ struct vt_stat vtstat; -+ struct vt_mode vt; - - INIT_G(); - -@@ -499,8 +515,10 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - fb_device = "/dev/fb0"; - cfg_filename = NULL; - fifo_filename = NULL; -- bCursorOff = 1 & getopt32(argv, "cs:d:i:f:", -- &G.image_filename, &fb_device, &cfg_filename, &fifo_filename); -+ opt_complementary = "T+"; // numeric params -+ bCursorOff = 1 & getopt32(argv, "cs:d:i:f:T:", -+ &G.image_filename, &fb_device, &cfg_filename, &fifo_filename, -+ &G.silent_tty); - - // parse configuration file - if (cfg_filename) -@@ -510,11 +528,43 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - if (!G.image_filename) - bb_show_usage(); - -+ fd_tty0 = get_console_fd_or_die(); -+ if (G.silent_tty) { -+ char buf[16]; -+ -+ /* Initialize TTY */ -+ bb_signals((1LL << SIGUSR1) | (1LL << SIGUSR2), sighandler); -+ snprintf(buf, sizeof(buf), "/dev/tty%d", G.silent_tty); -+ G.fd_tty_s = xopen(buf, O_RDWR | O_NOCTTY); -+ -+ /* Activate TTY */ -+ xioctl(fd_tty0, VT_GETSTATE, &vtstat); -+ active_vt = vtstat.v_active; -+ console_make_active(fd_tty0, G.silent_tty); -+ -+ /* Get notifications on console changes */ -+ vt.mode = VT_PROCESS; -+ vt.waitv = 0; -+ vt.relsig = SIGUSR1; -+ vt.acqsig = SIGUSR2; -+ ioctl(G.fd_tty_s, VT_SETMODE, &vt); -+ -+ /* Redirect all kernel messages to tty1 so that they don't get -+ * printed over our silent splash image. And clear it. */ -+ buf[0] = TIOCL_SETKMSGREDIRECT; -+ buf[1] = 1; -+ ioctl(G.fd_tty_s, TIOCLINUX, buf); -+ full_write(G.fd_tty_s, "\e[H\e[2J" "\e[?17;0c", 7+8); -+ ioctl(G.fd_tty_s, KDSETMODE, KD_GRAPHICS); -+ } else { -+ G.fd_tty_s = STDOUT_FILENO; -+ } -+ - fb_open(fb_device); - - if (fifo_filename && bCursorOff) { - // hide cursor (BEFORE any fb ops) -- full_write(STDOUT_FILENO, "\033[?25l", 6); -+ full_write(G.fd_tty_s, "\033[?25l", 6); - } - - fb_drawimage(); -@@ -522,6 +572,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - if (!fifo_filename) - return EXIT_SUCCESS; - -+ sig_block(SIGUSR1); - fp = xfopen_stdin(fifo_filename); - if (fp != stdin) { - // For named pipes, we want to support this: -@@ -537,8 +588,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - // and become an additional writer :) - open(fifo_filename, O_WRONLY); // errors are ignored - } -- - fb_drawprogressbar(0); -+ sig_unblock(SIGUSR1); -+ - // Block on read, waiting for some input. - // Use of <stdio.h> style I/O allows to correctly - // handle a case when we have many buffered lines -@@ -553,12 +605,29 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - #if DEBUG - DEBUG_MESSAGE(itoa(num)); - #endif -- fb_drawprogressbar(num); -+ sig_block(SIGUSR1); -+ if (!G.do_not_draw) -+ fb_drawprogressbar(num); -+ sig_unblock(SIGUSR1); - } - free(num_buf); - } - -- if (bCursorOff) // restore cursor -+ if (G.silent_tty) { -+ usleep(100*1000); -+ -+ ioctl(G.fd_tty_s, VT_RELDISP, 1); -+ ioctl(G.fd_tty_s, KDSETMODE, KD_TEXT); -+ vt.mode = VT_AUTO; -+ vt.waitv = 0; -+ ioctl(G.fd_tty_s, VT_SETMODE, &vt); -+ close(G.fd_tty_s); -+ -+ xioctl(fd_tty0, VT_GETSTATE, &vtstat); -+ if (vtstat.v_active == G.silent_tty) -+ console_make_active(fd_tty0, active_vt); -+ ioctl(fd_tty0, VT_DISALLOCATE, (void *)(ptrdiff_t)G.silent_tty); -+ } else if (bCursorOff) // restore cursor - full_write(STDOUT_FILENO, "\033[?25h", 6); - - return EXIT_SUCCESS; --- -2.13.2 - diff --git a/legacy/busybox/0005-udhcpc-set-default-discover-retries-to-5.patch b/legacy/busybox/0005-udhcpc-set-default-discover-retries-to-5.patch deleted file mode 100644 index 181acdb9a..000000000 --- a/legacy/busybox/0005-udhcpc-set-default-discover-retries-to-5.patch +++ /dev/null @@ -1,35 +0,0 @@ -From b67940090709f3bbd868557dd4d5317cb807250d Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 4 Aug 2016 11:08:35 +0200 -Subject: [PATCH 05/16] udhcpc: set default discover retries to 5 - -Some slower nics needs more attempts to get a lease ---- - networking/udhcp/dhcpc.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c -index 55f21c187..cc1d22c8e 100644 ---- a/networking/udhcp/dhcpc.c -+++ b/networking/udhcp/dhcpc.c -@@ -1203,7 +1203,7 @@ static void client_background(void) - //usage: "\n -p FILE Create pidfile" - //usage: "\n -B Request broadcast replies" - //usage: "\n -t N Send up to N discover packets (default 3)" --//usage: "\n -T SEC Pause between packets (default 3)" -+//usage: "\n -T SEC Pause between packets (default 5)" - //usage: "\n -A SEC Wait if lease is not obtained (default 20)" - //usage: "\n -n Exit if lease is not obtained" - //usage: "\n -q Exit after obtaining lease" -@@ -1247,7 +1247,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) - llist_t *list_x = NULL; - int tryagain_timeout = 20; - int discover_timeout = 3; -- int discover_retries = 3; -+ int discover_retries = 5; - uint32_t server_addr = server_addr; /* for compiler */ - uint32_t requested_ip = 0; - uint32_t xid = xid; /* for compiler */ --- -2.16.2 - diff --git a/legacy/busybox/0006-fbsplash-support-image-and-bar-alignment-and-positio.patch b/legacy/busybox/0006-fbsplash-support-image-and-bar-alignment-and-positio.patch deleted file mode 100644 index 65c423178..000000000 --- a/legacy/busybox/0006-fbsplash-support-image-and-bar-alignment-and-positio.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 64e2d2e495f82ef7ccc952bfa4216d1ff8ab3481 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Fri, 21 Nov 2014 16:06:34 +0200 -Subject: [PATCH 06/11] fbsplash: support image and bar alignment and - positioning -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Timo Teräs <timo.teras@iki.fi> ---- - miscutils/fbsplash.c | 91 +++++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 76 insertions(+), 15 deletions(-) - -diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c -index ec5947314..34bbf81f5 100644 ---- a/miscutils/fbsplash.c -+++ b/miscutils/fbsplash.c -@@ -53,6 +53,7 @@ - //usage: "\n -c Hide cursor" - //usage: "\n -d Framebuffer device (default /dev/fb0)" - //usage: "\n -i Config file (var=value):" -+//usage: "\n IMAGE_ALIGN" - //usage: "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" - //usage: "\n BAR_R,BAR_G,BAR_B" - //usage: "\n -f Control pipe (else exit after drawing image)" -@@ -71,13 +72,38 @@ - /* If you want logging messages on /tmp/fbsplash.log... */ - #define DEBUG 0 - -+enum { -+ image_align, -+ -+ image_posx, -+ image_posy, -+ bar_width, -+ bar_height, -+ bar_posx, -+ bar_posy, -+ bar_colr, -+ bar_colg, -+ bar_colb, -+ -+ debug -+}; -+ -+#define nimage_align ns[image_align] -+#define nbar_width ns[bar_width] -+#define nbar_height ns[bar_height] -+#define nbar_posx ns[bar_posx] -+#define nbar_posy ns[bar_posy] -+#define nbar_colr ns[bar_colr] -+#define nbar_colg ns[bar_colg] -+#define nbar_colb ns[bar_colb] -+ - struct globals { - #if DEBUG - bool bdebug_messages; // enable/disable logging - FILE *logfile_fd; // log file - #endif - unsigned char *addr; // pointer to framebuffer memory -- unsigned ns[7]; // n-parameters -+ unsigned ns[debug+1]; // n-parameters - const char *image_filename; - int silent_tty, fd_tty_s; - bool do_not_draw; -@@ -94,14 +120,6 @@ struct globals { - SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ - } while (0) - --#define nbar_width ns[0] // progress bar width --#define nbar_height ns[1] // progress bar height --#define nbar_posx ns[2] // progress bar horizontal position --#define nbar_posy ns[3] // progress bar vertical position --#define nbar_colr ns[4] // progress bar color red component --#define nbar_colg ns[5] // progress bar color green component --#define nbar_colb ns[6] // progress bar color blue component -- - #if DEBUG - #define DEBUG_MESSAGE(strMessage, args...) \ - if (G.bdebug_messages) { \ -@@ -382,7 +400,7 @@ static void fb_drawimage(void) - FILE *theme_file; - char *read_ptr; - unsigned char *pixline; -- unsigned i, j, width, height, line_size; -+ int i, j, width, height, line_size, xoffs, yoffs, xstart; - - if (LONE_DASH(G.image_filename)) { - theme_file = stdin; -@@ -432,18 +450,46 @@ static void fb_drawimage(void) - line_size = width*3; - pixline = xmalloc(line_size); - -+#if 0 - if (width > G.scr_var.xres) - width = G.scr_var.xres; - if (height > G.scr_var.yres) - height = G.scr_var.yres; -- for (j = 0; j < height; j++) { -+#endif -+ -+ xoffs = yoffs = 0; -+ switch (G.nimage_align % 3) { -+ case 1: xoffs = (G.scr_var.xres - width) / 2; break; -+ case 2: xoffs = G.scr_var.xres - width; break; -+ } -+ xstart = 0; -+ if (xoffs < 0) { -+ xstart = -xoffs; -+ width -= xstart; -+ xoffs = 0; -+ } -+ xoffs *= G.bytes_per_pixel; -+ if (width > G.scr_var.xres) -+ width = G.scr_var.xres; -+ -+ switch (G.nimage_align / 3) { -+ case 1: yoffs = (G.scr_var.yres - height) / 2; break; -+ case 2: yoffs = G.scr_var.yres - height; break; -+ } -+ -+ for (j = 0; j < height && yoffs < G.scr_var.yres; j++, yoffs++) { - unsigned char *pixel; - unsigned char *src; - - if (fread(pixline, 1, line_size, theme_file) != line_size) - bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); -+ -+ if (yoffs < 0) -+ continue; -+ - pixel = pixline; -- src = G.addr + j * G.scr_fix.line_length; -+ src = G.addr + yoffs * G.scr_fix.line_length + xoffs; -+ - for (i = 0; i < width; i++) { - unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]); - fb_write_pixel(src, thispix); -@@ -462,9 +508,17 @@ static void fb_drawimage(void) - */ - static void init(const char *cfg_filename) - { -+ static const char align_names[] ALIGN1 = -+ "LT\0" "CT\0" "RT\0" -+ "LM\0" "CM\0" "RM\0" -+ "LB\0" "CB\0" "RB\0"; - static const char param_names[] ALIGN1 = -+ "IMAGE_ALIGN\0" -+ -+ "IMAGE_X\0" "IMAGE_Y\0" - "BAR_WIDTH\0" "BAR_HEIGHT\0" - "BAR_LEFT\0" "BAR_TOP\0" -+ - "BAR_R\0" "BAR_G\0" "BAR_B\0" - #if DEBUG - "DEBUG\0" -@@ -474,14 +528,21 @@ static void init(const char *cfg_filename) - parser_t *parser = config_open2(cfg_filename, xfopen_stdin); - while (config_read(parser, token, 2, 2, "#=", - (PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) { -- unsigned val = xatoi_positive(token[1]); -+ unsigned val; - int i = index_in_strings(param_names, token[0]); -+ - if (i < 0) - bb_error_msg_and_die("syntax error: %s", token[0]); -- if (i >= 0 && i < 7) -+ -+ if (i <= image_align) -+ val = index_in_strings(align_names, token[1]); -+ else -+ val = xatoi_positive(token[1]); -+ -+ if (i < debug) - G.ns[i] = val; - #if DEBUG -- if (i == 7) { -+ if (i == debug) { - G.bdebug_messages = val; - if (G.bdebug_messages) - G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log"); --- -2.13.2 - diff --git a/legacy/busybox/0006-ping-make-ping-work-without-root-privileges.patch b/legacy/busybox/0006-ping-make-ping-work-without-root-privileges.patch deleted file mode 100644 index 630619b4a..000000000 --- a/legacy/busybox/0006-ping-make-ping-work-without-root-privileges.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 21d74f2989d0046e5b7c586f5a052643d5da8dcc Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Tue, 29 Mar 2016 18:59:22 +0200 -Subject: [PATCH 06/16] ping: make ping work without root privileges - ---- - networking/ping.c | 103 +++++++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 87 insertions(+), 16 deletions(-) - -diff --git a/networking/ping.c b/networking/ping.c -index d1d59d545..c0ebc0f9a 100644 ---- a/networking/ping.c -+++ b/networking/ping.c -@@ -163,6 +163,7 @@ enum { - pingsock = 0, - }; - -+static int using_dgram; - static void - #if ENABLE_PING6 - create_icmp_socket(len_and_sockaddr *lsa) -@@ -179,9 +180,23 @@ create_icmp_socket(void) - #endif - sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */ - if (sock < 0) { -- if (errno == EPERM) -- bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); -- bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); -+ if (errno != EPERM) -+ bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); -+#if defined(__linux__) || defined(__APPLE__) -+ /* We don't have root privileges. Try SOCK_DGRAM instead. -+ * Linux needs net.ipv4.ping_group_range for this to work. -+ * MacOSX allows ICMP_ECHO, ICMP_TSTAMP or ICMP_MASKREQ -+ */ -+#if ENABLE_PING6 -+ if (lsa->u.sa.sa_family == AF_INET6) -+ sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); -+ else -+#endif -+ sock = socket(AF_INET, SOCK_DGRAM, 1); /* 1 == ICMP */ -+ if (sock < 0) -+#endif -+ bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); -+ using_dgram = 1; - } - - xmove_fd(sock, pingsock); -@@ -234,10 +249,12 @@ static void ping4(len_and_sockaddr *lsa) - bb_perror_msg("recvfrom"); - continue; - } -- if (c >= 76) { /* ip + icmp */ -- struct iphdr *iphdr = (struct iphdr *) G.packet; -+ if (c >= 76 || using_dgram && (c == 64)) { /* ip + icmp */ -+ if(!using_dgram) { -+ struct iphdr *iphdr = (struct iphdr *) G.packet; - -- pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ -+ pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ -+ } else pkt = (struct icmp *) G.packet; - if (pkt->icmp_id != G.myid) - continue; /* not our ping */ - if (pkt->icmp_type == ICMP_ECHOREPLY) -@@ -634,19 +651,21 @@ static void unpack_tail(int sz, uint32_t *tp, - } - static void unpack4(char *buf, int sz, struct sockaddr_in *from) - { -- struct icmp *icmppkt; - struct iphdr *iphdr; -+ struct icmp *icmppkt; - int hlen; - - /* discard if too short */ - if (sz < (datalen + ICMP_MINLEN)) - return; -+ if(!using_dgram) { -+ /* check IP header */ -+ iphdr = (struct iphdr *) buf; -+ hlen = iphdr->ihl << 2; -+ sz -= hlen; -+ icmppkt = (struct icmp *) (buf + hlen); -+ } else icmppkt = (struct icmp *) buf; - -- /* check IP header */ -- iphdr = (struct iphdr *) buf; -- hlen = iphdr->ihl << 2; -- sz -= hlen; -- icmppkt = (struct icmp *) (buf + hlen); - if (icmppkt->icmp_id != myid) - return; /* not our ping */ - -@@ -658,7 +677,7 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from) - tp = (uint32_t *) icmppkt->icmp_data; - unpack_tail(sz, tp, - inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), -- recv_seq, iphdr->ttl); -+ recv_seq, using_dgram ? 42 : iphdr->ttl); - } else if (icmppkt->icmp_type != ICMP_ECHO) { - bb_error_msg("warning: got ICMP %d (%s)", - icmppkt->icmp_type, -@@ -702,11 +721,31 @@ static void ping4(len_and_sockaddr *lsa) - int sockopt; - - pingaddr.sin = lsa->u.sin; -- if (source_lsa) { -+ if (source_lsa && !using_dgram) { - if (setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_IF, - &source_lsa->u.sa, source_lsa->len)) - bb_error_msg_and_die("can't set multicast source interface"); - xbind(pingsock, &source_lsa->u.sa, source_lsa->len); -+ } else if(using_dgram) { -+ struct sockaddr_in sa; -+ socklen_t sl; -+ -+ sa.sin_family = AF_INET; -+ sa.sin_port = 0; -+ sa.sin_addr.s_addr = source_lsa ? -+ source_lsa->u.sin.sin_addr.s_addr : 0; -+ sl = sizeof(sa); -+ -+ if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) { -+ perror("bind"); -+ exit(2); -+ } -+ -+ if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) { -+ perror("getsockname"); -+ exit(2); -+ } -+ myid = sa.sin_port; - } - - /* enable broadcast pings */ -@@ -723,6 +762,15 @@ static void ping4(len_and_sockaddr *lsa) - setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl); - } - -+ if(using_dgram) { -+ int hold = 65536; -+ if (setsockopt(pingsock, SOL_IP, IP_RECVTTL, (char *)&hold, sizeof(hold))) -+ perror("WARNING: setsockopt(IP_RECVTTL)"); -+ if (setsockopt(pingsock, SOL_IP, IP_RETOPTS, (char *)&hold, sizeof(hold))) -+ perror("WARNING: setsockopt(IP_RETOPTS)"); -+ -+ } -+ - signal(SIGINT, print_stats_and_exit); - - /* start the ping's going ... */ -@@ -756,10 +804,33 @@ static void ping6(len_and_sockaddr *lsa) - char control_buf[CMSG_SPACE(36)]; - - pingaddr.sin6 = lsa->u.sin6; -- if (source_lsa) -+ if (source_lsa && !using_dgram) - xbind(pingsock, &source_lsa->u.sa, source_lsa->len); -+ else if(using_dgram) { -+ struct sockaddr_in6 sa = {0}; -+ socklen_t sl; -+ -+ sa.sin6_family = AF_INET6; -+ sa.sin6_port = 0; -+ if(source_lsa) { -+ memcpy(&sa.sin6_addr, &source_lsa->u.sin6.sin6_addr, sizeof(struct in6_addr)); -+ } -+ sl = sizeof(sa); -+ -+ if (bind(pingsock, (struct sockaddr *) &sa, sl) == -1) { -+ perror("bind"); -+ exit(2); -+ } -+ -+ if (getsockname(pingsock, (struct sockaddr *) &sa, &sl) == -1) { -+ perror("getsockname"); -+ exit(2); -+ } -+ myid = sa.sin6_port; -+ } - - #ifdef ICMP6_FILTER -+ if(!using_dgram) - { - struct icmp6_filter filt; - if (!(option_mask32 & OPT_VERBOSE)) { -@@ -890,7 +961,7 @@ static int common_ping_main(int opt, char **argv) - if (opt & OPT_p) - G.pattern = xstrtou_range(str_p, 16, 0, 255); - -- myid = (uint16_t) getpid(); -+ if (!using_dgram) myid = (uint16_t) getpid(); - hostname = argv[optind]; - #if ENABLE_PING6 - { --- -2.16.2 - diff --git a/legacy/busybox/0007-depmod-support-generating-kmod-binary-index-files.patch b/legacy/busybox/0007-depmod-support-generating-kmod-binary-index-files.patch deleted file mode 100644 index 8b89902de..000000000 --- a/legacy/busybox/0007-depmod-support-generating-kmod-binary-index-files.patch +++ /dev/null @@ -1,516 +0,0 @@ -From ab4df89615fc2c5726b4ce55546e4dc098211a0b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Sun, 25 Oct 2015 22:21:41 +0200 -Subject: [PATCH 07/11] depmod: support generating kmod binary index files -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This allows to use busybox depmod, and run daemons -using libkmod (or even kmod modprobe if needed). - -About +1500 bytes when enabled. This patch merges some -depmod code paths, so when this is disabled it shrinks -the code size a little bit. - -Signed-off-by: Timo Teräs <timo.teras@iki.fi> ---- - modutils/Config.src | 9 ++ - modutils/depmod.c | 281 ++++++++++++++++++++++++++++++++++++++++++---------- - modutils/modprobe.c | 15 --- - modutils/modutils.c | 31 ++++++ - modutils/modutils.h | 16 +++ - 5 files changed, 286 insertions(+), 66 deletions(-) - -diff --git a/modutils/Config.src b/modutils/Config.src -index 9b76c83d2..9e3b9b71e 100644 ---- a/modutils/Config.src -+++ b/modutils/Config.src -@@ -152,6 +152,15 @@ config FEATURE_MODUTILS_ALIAS - - Say Y if unsure. - -+config FEATURE_MODUTILS_BIN -+ bool "Support for the kmod .bin file format" -+ default n -+ depends on DEPMOD && !MODPROBE_SMALL -+ help -+ Generate kmod compatible binary index files for .dep, .alias, -+ .symbols and .builtin files. Allows mixing use of busybox -+ modutils and kmod (binaries and library). -+ - config FEATURE_MODUTILS_SYMBOLS - bool "Support module.symbols file" - default y -diff --git a/modutils/depmod.c b/modutils/depmod.c -index b7965ebd2..73ba7d0f4 100644 ---- a/modutils/depmod.c -+++ b/modutils/depmod.c -@@ -2,7 +2,7 @@ - /* - * depmod - generate modules.dep - * Copyright (c) 2008 Bernhard Reutner-Fischer -- * Copyrihgt (c) 2008 Timo Teras <timo.teras@iki.fi> -+ * Copyrihgt (c) 2008-2015 Timo Teras <timo.teras@iki.fi> - * Copyright (c) 2008 Vladimir Dronnikov - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. -@@ -26,6 +26,24 @@ - #include "modutils.h" - #include <sys/utsname.h> /* uname() */ - -+#define INDEX_MINCHAR 32 -+#define INDEX_MAXCHAR 128 -+ -+typedef struct index_node { -+ char *prefix; -+ llist_t *values; -+ struct index_node *children[INDEX_MAXCHAR-INDEX_MINCHAR]; -+} index_node; -+ -+struct globals { -+ module_db db; -+ index_node *root_node; -+} FIX_ALIASING; -+#define G (*ptr_to_globals) -+#define INIT_G() do { \ -+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ -+} while (0) -+ - /* - * Theory of operation: - * - iterate over all modules and record their full path -@@ -53,18 +71,12 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA - - for (ptr = image; ptr < image + len - 10; ptr++) { - if (is_prefixed_with(ptr, "depends=")) { -- char *u; -- - ptr += 8; -- for (u = ptr; *u; u++) -- if (*u == '-') -- *u = '_'; -- ptr += string_to_llist(ptr, &e->deps, ","); -+ string_to_llist(replace_underscores(ptr), &e->deps, ","); - } else if (ENABLE_FEATURE_MODUTILS_ALIAS - && is_prefixed_with(ptr, "alias=") - ) { -- llist_add_to(&e->aliases, xstrdup(ptr + 6)); -- ptr += strlen(ptr); -+ llist_add_to(&e->aliases, replace_underscores(xstrdup(ptr + 6))); - } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS - && is_prefixed_with(ptr, "__ksymtab_") - ) { -@@ -74,9 +86,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA - ) { - continue; - } -- llist_add_to(&e->symbols, xstrdup(ptr)); -- ptr += strlen(ptr); -- } -+ llist_add_to(&e->symbols, xasprintf("symbol:%s", ptr)); -+ } else -+ continue; -+ ptr += strlen(ptr); - } - free(image); - -@@ -108,12 +121,6 @@ static void order_dep_list(module_db *modules, module_entry *start, llist_t *add - } - } - --static void xfreopen_write(const char *file, FILE *f) --{ -- if (freopen(file, "w", f) == NULL) -- bb_perror_msg_and_die("can't open '%s'", file); --} -- - //usage:#if !ENABLE_MODPROBE_SMALL - //usage:#define depmod_trivial_usage "[-n] [-b BASE] [VERSION] [MODFILES]..." - //usage:#define depmod_full_usage "\n\n" -@@ -167,6 +174,169 @@ enum { - OPT_C = (1 << 9), /* -C,--config etc_modules_conf: ignored */ - }; - -+/* Support for the mod binary index generation */ -+ -+static void index_init(const char *filename) -+{ -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ index_node *n; -+ -+ n = xzalloc(sizeof(index_node)); -+ n->prefix = xstrdup(""); -+ G.root_node = n; -+ } -+ -+ if (filename && !(option_mask32 & OPT_n)) { -+ if (freopen(filename, "w", stdout) == NULL) -+ bb_perror_msg_and_die("can't open '%s'", filename); -+ } -+} -+ -+static void index_add(const char *key, char *value, const char *prefix) -+{ -+ if (prefix && *prefix) -+ printf("%s%s %s\n", prefix, key, value); -+ else if (prefix) -+ printf("%s\n", value); -+ -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ index_node *cur = G.root_node, *n; -+ unsigned i = 0, j, ch; -+ -+ while (1) { -+ /* Ensure node->prefix is a prefix of &str[i]. -+ * If it is not already, then we must split node. */ -+ for (j = 0; cur->prefix[j]; j++) { -+ ch = cur->prefix[j]; -+ if (ch != key[i+j]) { -+ /* New child is copy of node with prefix[j+1..N] */ -+ n = xzalloc(sizeof(index_node)); -+ n->prefix = xstrdup(&cur->prefix[j+1]); -+ n->values = cur->values; -+ memcpy(n->children, cur->children, sizeof(n->children)); -+ -+ /* Parent has prefix[0..j], child at prefix[j] */ -+ cur->prefix[j] = '\0'; -+ cur->values = NULL; -+ memset(cur->children, 0, sizeof(cur->children)); -+ cur->children[ch-INDEX_MINCHAR] = n; -+ break; -+ } -+ } -+ i += j; -+ -+ ch = key[i]; -+ if (ch == 0) -+ break; -+ -+ if (ch < INDEX_MINCHAR || ch >= INDEX_MAXCHAR) -+ bb_error_msg_and_die("bad module name"); -+ -+ ch -= INDEX_MINCHAR; -+ if (!cur->children[ch]) { -+ n = xzalloc(sizeof(index_node)); -+ cur->children[ch] = n; -+ n->prefix = xstrdup(&key[i+1]); -+ cur = n; -+ break; -+ } -+ -+ /* Descend into child node and continue */ -+ cur = cur->children[ch]; -+ i++; -+ } -+ -+ llist_add_to(&cur->values, value); -+ } -+} -+ -+static uint32_t index_write_node(FILE *out, index_node *n, void (*freeit)(void *data)) -+{ -+ uint32_t child_offs[INDEX_MAXCHAR-INDEX_MINCHAR]; -+ uint32_t offset; -+ uint8_t first = 255, last = 0; -+ unsigned i; -+ -+ for (i = 0; i < INDEX_MAXCHAR-INDEX_MINCHAR; i++) { -+ child_offs[i] = 0; -+ if (!n->children[i]) -+ continue; -+ child_offs[i] = index_write_node(out, n->children[i], freeit); -+ if (first > INDEX_MAXCHAR) -+ first = i; -+ last = i; -+ } -+ -+ offset = ftell(out); -+ -+ if (n->prefix[0]) { -+ fputs(n->prefix, out); -+ fputc('\0', out); -+ offset |= INDEX_NODE_PREFIX; -+ } -+ -+ if (first < INDEX_MAXCHAR) { -+ fputc(first + INDEX_MINCHAR, out); -+ fputc(last + INDEX_MINCHAR, out); -+ fwrite(child_offs + first, sizeof(uint32_t), last - first + 1, out); -+ offset |= INDEX_NODE_CHILDS; -+ } -+ -+ if (n->values) { -+ const llist_t *v; -+ unsigned int cnt; -+ uint32_t u; -+ -+ n->values = llist_rev(n->values); -+ for (v = n->values, cnt = 0; v != NULL; v = v->link, cnt++); -+ u = htonl(cnt); -+ fwrite(&u, sizeof(u), 1, out); -+ for (v = n->values, cnt = 0; v != NULL; v = v->link, cnt++) { -+ u = htonl(cnt); -+ fwrite(&u, sizeof(u), 1, out); -+ fputs(v->data, out); -+ fputc('\0', out); -+ } -+ offset |= INDEX_NODE_VALUES; -+ } -+ -+ llist_free(n->values, freeit); -+ free(n->prefix); -+ free(n); -+ -+ return htonl(offset); -+} -+ -+static void index_dump(const char *filename, int deps_file) -+{ -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ FILE *out; -+ uint32_t header[3] = { -+ htonl(INDEX_MAGIC), -+ htonl(INDEX_VERSION), -+ }; -+ -+ if (option_mask32 & OPT_n) -+ filename = "/dev/null"; -+ else -+ filename = xasprintf("tmp.%s.bin", filename); -+ -+ out = xfopen_for_write(filename); -+ fwrite(header, sizeof(uint32_t), 3, out); -+ header[2] = index_write_node(out, G.root_node, deps_file ? free : 0); -+ rewind(out); -+ G.root_node = NULL; -+ fwrite(header, sizeof(uint32_t), 3, out); -+ if (fclose(out)) { -+ remove(filename); -+ bb_error_msg_and_die(bb_msg_write_error); -+ } -+ /* .bin files are mmap'ed; not renaming it may crash -+ * long standing daemon using libkmod */ -+ rename_or_warn(filename, filename + 4); -+ } -+} -+ - int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int depmod_main(int argc UNUSED_PARAM, char **argv) - { -@@ -178,6 +348,8 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) - unsigned i; - int tmp; - -+ INIT_G(); -+ - getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); - argv += optind; - -@@ -210,53 +382,60 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) - } - - /* Generate dependency and alias files */ -- if (!(option_mask32 & OPT_n)) -- xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout); -- -+ index_init(CONFIG_DEFAULT_DEPMOD_FILE); - moddb_foreach_module(&modules, m, i) { -- printf("%s:", m->name); -- -+ char *buf = xasprintf("%s:", m->name); - order_dep_list(&modules, m, m->deps); -+ - while (m->dnext != m) { - dep = m->dnext; -- printf(" %s", dep->name); -- -+ buf = gather_options_str(buf, dep->name); - /* unlink current entry */ - dep->dnext->dprev = dep->dprev; - dep->dprev->dnext = dep->dnext; - dep->dnext = dep->dprev = dep; - } -- bb_putchar('\n'); -+ index_add(m->modname, buf, ""); - } -- --#if ENABLE_FEATURE_MODUTILS_ALIAS -- if (!(option_mask32 & OPT_n)) -- xfreopen_write("modules.alias", stdout); -- moddb_foreach_module(&modules, m, i) { -- while (m->aliases) { -- /* -- * Last word used to be a basename -- * (filename with path and .ko.* stripped) -- * at the time of module-init-tools 3.4. -- * kmod v.12 uses module name, i.e., s/-/_/g. -- */ -- printf("alias %s %s\n", -- (char*)llist_pop(&m->aliases), -- m->modname); -+ index_dump(CONFIG_DEFAULT_DEPMOD_FILE, 1); -+ -+ if (ENABLE_FEATURE_MODUTILS_ALIAS) { -+ index_init("modules.alias"); -+ moddb_foreach_module(&modules, m, i) { -+ while (m->aliases) { -+ /* -+ * Last word used to be a basename -+ * (filename with path and .ko.* stripped) -+ * at the time of module-init-tools 3.4. -+ * kmod v.12 uses module name, i.e., s/-/_/g. -+ */ -+ index_add((char*)llist_pop(&m->aliases), m->modname, "alias "); -+ } - } -+ index_dump("modules.alias", 0); - } --#endif --#if ENABLE_FEATURE_MODUTILS_SYMBOLS -- if (!(option_mask32 & OPT_n)) -- xfreopen_write("modules.symbols", stdout); -- moddb_foreach_module(&modules, m, i) { -- while (m->symbols) { -- printf("alias symbol:%s %s\n", -- (char*)llist_pop(&m->symbols), -- m->modname); -+ if (ENABLE_FEATURE_MODUTILS_SYMBOLS) { -+ index_init("modules.symbols"); -+ moddb_foreach_module(&modules, m, i) { -+ while (m->symbols) { -+ index_add((char*)llist_pop(&m->symbols), m->modname, "alias "); -+ } -+ } -+ index_dump("modules.symbols", 0); -+ } -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ char line[PATH_MAX], modname[MODULE_NAME_LEN]; -+ FILE *in; -+ -+ index_init(NULL); -+ in = xfopen_for_read("modules.builtin"); -+ while (fgets(line, sizeof(line), in) != NULL) { -+ filename2modname(line, modname); -+ index_add(modname, (char *) "", 0); - } -+ fclose(in); -+ index_dump("modules.builtin", 0); - } --#endif - - if (ENABLE_FEATURE_CLEAN_UP) - moddb_free(&modules); -diff --git a/modutils/modprobe.c b/modutils/modprobe.c -index 51ede9204..d1fcc0b7f 100644 ---- a/modutils/modprobe.c -+++ b/modutils/modprobe.c -@@ -192,21 +192,6 @@ struct globals { - - static int read_config(const char *path); - --static char *gather_options_str(char *opts, const char *append) --{ -- /* Speed-optimized. We call gather_options_str many times. */ -- if (append) { -- if (opts == NULL) { -- opts = xstrdup(append); -- } else { -- int optlen = strlen(opts); -- opts = xrealloc(opts, optlen + strlen(append) + 2); -- sprintf(opts + optlen, " %s", append); -- } -- } -- return opts; --} -- - static struct module_entry *get_or_add_modentry(const char *module) - { - return moddb_get_or_create(&G.db, module); -diff --git a/modutils/modutils.c b/modutils/modutils.c -index 6f7cd9721..257089af4 100644 ---- a/modutils/modutils.c -+++ b/modutils/modutils.c -@@ -66,6 +66,21 @@ void FAST_FUNC moddb_free(module_db *db) - } - } - -+char * FAST_FUNC gather_options_str(char *opts, const char *append) -+{ -+ /* Speed-optimized. We call gather_options_str many times. */ -+ if (append) { -+ if (opts == NULL) { -+ opts = xstrdup(append); -+ } else { -+ int optlen = strlen(opts); -+ opts = xrealloc(opts, optlen + strlen(append) + 2); -+ sprintf(opts + optlen, " %s", append); -+ } -+ } -+ return opts; -+} -+ - void FAST_FUNC replace(char *s, char what, char with) - { - while (*s) { -@@ -75,6 +90,22 @@ void FAST_FUNC replace(char *s, char what, char with) - } - } - -+char* FAST_FUNC replace_underscores(char *s) -+{ -+ int i; -+ for (i = 0; s[i]; i++) { -+ switch (s[i]) { -+ case '-': -+ s[i] = '_'; -+ break; -+ case '[': -+ i += strcspn(&s[i], "]"); -+ break; -+ } -+ } -+ return s; -+} -+ - int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) - { - char *tok; -diff --git a/modutils/modutils.h b/modutils/modutils.h -index 4a702e97c..73e816028 100644 ---- a/modutils/modutils.h -+++ b/modutils/modutils.h -@@ -18,6 +18,20 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN - #define MODULE_NAME_LEN 256 - #define MODULE_HASH_SIZE 256 - -+/* .bin index format definitions */ -+#define INDEX_MAGIC 0xB007F457 -+#define INDEX_VERSION_MAJOR 0x0002 -+#define INDEX_VERSION_MINOR 0x0001 -+#define INDEX_VERSION ((INDEX_VERSION_MAJOR<<16)|INDEX_VERSION_MINOR) -+ -+enum node_offset { -+ INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */ -+ INDEX_NODE_PREFIX = 0x80000000, -+ INDEX_NODE_VALUES = 0x40000000, -+ INDEX_NODE_CHILDS = 0x20000000, -+ INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */ -+}; -+ - typedef struct module_entry { - struct module_entry *next; - char *name, *modname; -@@ -47,7 +61,9 @@ module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC; - module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC; - void moddb_free(module_db *db) FAST_FUNC; - -+char *gather_options_str(char *opts, const char *append) FAST_FUNC; - void replace(char *s, char what, char with) FAST_FUNC; -+char *replace_underscores(char *s) FAST_FUNC; - int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC; - char *filename2modname(const char *filename, char *modname) FAST_FUNC; - #if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS --- -2.13.2 - diff --git a/legacy/busybox/0007-fbsplash-support-console-switching.patch b/legacy/busybox/0007-fbsplash-support-console-switching.patch deleted file mode 100644 index ef226d009..000000000 --- a/legacy/busybox/0007-fbsplash-support-console-switching.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 377e2f20c1034de1195fd900fc637821952cfa49 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Mon, 24 Sep 2012 07:58:29 +0300 -Subject: [PATCH 07/16] fbsplash: support console switching - ---- - miscutils/fbsplash.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 75 insertions(+), 7 deletions(-) - -diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c -index 5b2e5ac56..bc80f728c 100644 ---- a/miscutils/fbsplash.c -+++ b/miscutils/fbsplash.c -@@ -47,7 +47,7 @@ - //kbuild:lib-$(CONFIG_FBSPLASH) += fbsplash.o - - //usage:#define fbsplash_trivial_usage --//usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD]" -+//usage: "-s IMGFILE [-c] [-d DEV] [-i INIFILE] [-f CMD] [-T tty]" - //usage:#define fbsplash_full_usage "\n\n" - //usage: " -s Image" - //usage: "\n -c Hide cursor" -@@ -57,11 +57,17 @@ - //usage: "\n BAR_R,BAR_G,BAR_B" - //usage: "\n -f Control pipe (else exit after drawing image)" - //usage: "\n commands: 'NN' (% for progress bar) or 'exit'" -+//usage: "\n -T Switch to TTY to hide all console messages" - - #include "libbb.h" - #include "common_bufsiz.h" - #include <linux/fb.h> - -+#include <sys/vt.h> -+#include <sys/ioctl.h> -+#include <linux/tiocl.h> -+#include <linux/kd.h> -+ - /* If you want logging messages on /tmp/fbsplash.log... */ - #define DEBUG 0 - -@@ -75,6 +81,8 @@ struct globals { - unsigned char *addr; // pointer to framebuffer memory - unsigned ns[7]; // n-parameters - const char *image_filename; -+ int silent_tty, fd_tty_s; -+ bool do_not_draw; - struct fb_var_screeninfo scr_var; - struct fb_fix_screeninfo scr_fix; - unsigned bytes_per_pixel; -@@ -485,6 +493,11 @@ static void init(const char *cfg_filename) - config_close(parser); - } - -+static void sighandler(int sig) -+{ -+ ioctl(G.fd_tty_s, VT_RELDISP, sig == SIGUSR1 ? 1 : 2); -+ G.do_not_draw = (sig != SIGUSR2); -+} - - int fbsplash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int fbsplash_main(int argc UNUSED_PARAM, char **argv) -@@ -494,6 +507,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - char *num_buf; - unsigned num; - bool bCursorOff; -+ int fd_tty0, active_vt; -+ struct vt_stat vtstat; -+ struct vt_mode vt; - - INIT_G(); - -@@ -501,8 +517,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - fb_device = "/dev/fb0"; - cfg_filename = NULL; - fifo_filename = NULL; -- bCursorOff = 1 & getopt32(argv, "cs:d:i:f:", -- &G.image_filename, &fb_device, &cfg_filename, &fifo_filename); -+ bCursorOff = 1 & getopt32(argv, "cs:d:i:f:T:", -+ &G.image_filename, &fb_device, &cfg_filename, &fifo_filename, -+ &G.silent_tty); - - // parse configuration file - if (cfg_filename) -@@ -512,11 +529,43 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - if (!G.image_filename) - bb_show_usage(); - -+ fd_tty0 = get_console_fd_or_die(); -+ if (G.silent_tty) { -+ char buf[16]; -+ -+ /* Initialize TTY */ -+ bb_signals((1LL << SIGUSR1) | (1LL << SIGUSR2), sighandler); -+ snprintf(buf, sizeof(buf), "/dev/tty%d", G.silent_tty); -+ G.fd_tty_s = xopen(buf, O_RDWR | O_NOCTTY); -+ -+ /* Activate TTY */ -+ xioctl(fd_tty0, VT_GETSTATE, &vtstat); -+ active_vt = vtstat.v_active; -+ console_make_active(fd_tty0, G.silent_tty); -+ -+ /* Get notifications on console changes */ -+ vt.mode = VT_PROCESS; -+ vt.waitv = 0; -+ vt.relsig = SIGUSR1; -+ vt.acqsig = SIGUSR2; -+ ioctl(G.fd_tty_s, VT_SETMODE, &vt); -+ -+ /* Redirect all kernel messages to tty1 so that they don't get -+ * printed over our silent splash image. And clear it. */ -+ buf[0] = TIOCL_SETKMSGREDIRECT; -+ buf[1] = 1; -+ ioctl(G.fd_tty_s, TIOCLINUX, buf); -+ full_write(G.fd_tty_s, "\e[H\e[2J" "\e[?17;0c", 7+8); -+ ioctl(G.fd_tty_s, KDSETMODE, KD_GRAPHICS); -+ } else { -+ G.fd_tty_s = STDOUT_FILENO; -+ } -+ - fb_open(fb_device); - - if (fifo_filename && bCursorOff) { - // hide cursor (BEFORE any fb ops) -- full_write(STDOUT_FILENO, ESC"[?25l", 6); -+ full_write(G.fd_tty_s, ESC"[?25l", 6); - } - - fb_drawimage(); -@@ -524,6 +573,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - if (!fifo_filename) - return EXIT_SUCCESS; - -+ sig_block(SIGUSR1); - fp = xfopen_stdin(fifo_filename); - if (fp != stdin) { - // For named pipes, we want to support this: -@@ -539,8 +589,9 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - // and become an additional writer :) - open(fifo_filename, O_WRONLY); // errors are ignored - } -- - fb_drawprogressbar(0); -+ sig_unblock(SIGUSR1); -+ - // Block on read, waiting for some input. - // Use of <stdio.h> style I/O allows to correctly - // handle a case when we have many buffered lines -@@ -555,12 +606,29 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) - #if DEBUG - DEBUG_MESSAGE(itoa(num)); - #endif -- fb_drawprogressbar(num); -+ sig_block(SIGUSR1); -+ if (!G.do_not_draw) -+ fb_drawprogressbar(num); -+ sig_unblock(SIGUSR1); - } - free(num_buf); - } - -- if (bCursorOff) // restore cursor -+ if (G.silent_tty) { -+ usleep(100*1000); -+ -+ ioctl(G.fd_tty_s, VT_RELDISP, 1); -+ ioctl(G.fd_tty_s, KDSETMODE, KD_TEXT); -+ vt.mode = VT_AUTO; -+ vt.waitv = 0; -+ ioctl(G.fd_tty_s, VT_SETMODE, &vt); -+ close(G.fd_tty_s); -+ -+ xioctl(fd_tty0, VT_GETSTATE, &vtstat); -+ if (vtstat.v_active == G.silent_tty) -+ console_make_active(fd_tty0, active_vt); -+ ioctl(fd_tty0, VT_DISALLOCATE, (void *)(ptrdiff_t)G.silent_tty); -+ } else if (bCursorOff) // restore cursor - full_write(STDOUT_FILENO, ESC"[?25h", 6); - - return EXIT_SUCCESS; --- -2.16.2 - diff --git a/legacy/busybox/0008-diff-add-support-for-no-dereference.patch b/legacy/busybox/0008-diff-add-support-for-no-dereference.patch deleted file mode 100644 index 95063a863..000000000 --- a/legacy/busybox/0008-diff-add-support-for-no-dereference.patch +++ /dev/null @@ -1,63 +0,0 @@ -From d70be9891718ffb94ea9946cc3540b1b62eced77 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Fri, 25 Jul 2014 15:28:33 +0200 -Subject: [PATCH 08/11] diff: add support for --no-dereference - -Add flag for not following symlinks when recursing - -function old new delta -.rodata 7934 7967 +33 -diff_longopts 253 270 +17 -packed_usage 1704 1720 +16 -diff_main 1665 1662 -3 ------------------------------------------------------------------------------- -(add/remove: 0/0 grow/shrink: 3/1 up/down: 66/-3) Total: 63 bytes - -Signed-off-by: Natanael Copa <ncopa@alpinelinux.org> ---- - editors/diff.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/editors/diff.c b/editors/diff.c -index 7687518f3..f07cafb19 100644 ---- a/editors/diff.c -+++ b/editors/diff.c -@@ -115,6 +115,9 @@ - //usage: "\n -N Treat absent files as empty" - //usage: "\n -q Output only whether files differ" - //usage: "\n -r Recurse" -+//usage: IF_LONG_OPTS( -+//usage: "\n --no-dereference Don't follow symlinks" -+//usage: ) - //usage: "\n -S Start with FILE when comparing directories" - //usage: "\n -T Make tabs line up by prefixing a tab when necessary" - //usage: "\n -s Report when two files are the same" -@@ -156,6 +159,7 @@ enum { /* Commandline flags */ - FLAG_p, /* not implemented */ - FLAG_B, - FLAG_E, /* not implemented */ -+ FLAG_no_deref, - }; - #define FLAG(x) (1 << FLAG_##x) - -@@ -869,7 +873,8 @@ static void diffdir(char *p[2], const char *s_start) - * Using list.len to specify its length, - * add_to_dirlist will remove it. */ - list[i].len = strlen(p[i]); -- recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS, -+ recursive_action(p[i], ACTION_RECURSE | -+ ((option_mask32 & FLAG(no_deref)) ? 0 : ACTION_FOLLOWLINKS), - add_to_dirlist, skip_dir, &list[i], 0); - /* Sort dl alphabetically. - * GNU diff does this ignoring any number of trailing dots. -@@ -966,6 +971,7 @@ static const char diff_longopts[] ALIGN1 = - "report-identical-files\0" No_argument "s" - "starting-file\0" Required_argument "S" - "minimal\0" No_argument "d" -+ "no-dereference\0" No_argument "\xff" - ; - #endif - --- -2.13.2 - diff --git a/legacy/busybox/0008-fbsplash-support-image-and-bar-alignment-and-positio.patch b/legacy/busybox/0008-fbsplash-support-image-and-bar-alignment-and-positio.patch deleted file mode 100644 index b0cb5cc3d..000000000 --- a/legacy/busybox/0008-fbsplash-support-image-and-bar-alignment-and-positio.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 97fcb49bfbe74fa17a52e63b2196d8a5c3b27d93 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Fri, 21 Nov 2014 16:06:34 +0200 -Subject: [PATCH 08/16] fbsplash: support image and bar alignment and - positioning - ---- - miscutils/fbsplash.c | 91 +++++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 76 insertions(+), 15 deletions(-) - -diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c -index bc80f728c..9089131b8 100644 ---- a/miscutils/fbsplash.c -+++ b/miscutils/fbsplash.c -@@ -53,6 +53,7 @@ - //usage: "\n -c Hide cursor" - //usage: "\n -d Framebuffer device (default /dev/fb0)" - //usage: "\n -i Config file (var=value):" -+//usage: "\n IMAGE_ALIGN" - //usage: "\n BAR_LEFT,BAR_TOP,BAR_WIDTH,BAR_HEIGHT" - //usage: "\n BAR_R,BAR_G,BAR_B" - //usage: "\n -f Control pipe (else exit after drawing image)" -@@ -73,13 +74,38 @@ - - #define ESC "\033" - -+enum { -+ image_align, -+ -+ image_posx, -+ image_posy, -+ bar_width, -+ bar_height, -+ bar_posx, -+ bar_posy, -+ bar_colr, -+ bar_colg, -+ bar_colb, -+ -+ debug -+}; -+ -+#define nimage_align ns[image_align] -+#define nbar_width ns[bar_width] -+#define nbar_height ns[bar_height] -+#define nbar_posx ns[bar_posx] -+#define nbar_posy ns[bar_posy] -+#define nbar_colr ns[bar_colr] -+#define nbar_colg ns[bar_colg] -+#define nbar_colb ns[bar_colb] -+ - struct globals { - #if DEBUG - bool bdebug_messages; // enable/disable logging - FILE *logfile_fd; // log file - #endif - unsigned char *addr; // pointer to framebuffer memory -- unsigned ns[7]; // n-parameters -+ unsigned ns[debug+1]; // n-parameters - const char *image_filename; - int silent_tty, fd_tty_s; - bool do_not_draw; -@@ -96,14 +122,6 @@ struct globals { - SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ - } while (0) - --#define nbar_width ns[0] // progress bar width --#define nbar_height ns[1] // progress bar height --#define nbar_posx ns[2] // progress bar horizontal position --#define nbar_posy ns[3] // progress bar vertical position --#define nbar_colr ns[4] // progress bar color red component --#define nbar_colg ns[5] // progress bar color green component --#define nbar_colb ns[6] // progress bar color blue component -- - #if DEBUG - #define DEBUG_MESSAGE(strMessage, args...) \ - if (G.bdebug_messages) { \ -@@ -384,7 +402,7 @@ static void fb_drawimage(void) - FILE *theme_file; - char *read_ptr; - unsigned char *pixline; -- unsigned i, j, width, height, line_size; -+ int i, j, width, height, line_size, xoffs, yoffs, xstart; - - if (LONE_DASH(G.image_filename)) { - theme_file = stdin; -@@ -434,18 +452,46 @@ static void fb_drawimage(void) - line_size = width*3; - pixline = xmalloc(line_size); - -+#if 0 - if (width > G.scr_var.xres) - width = G.scr_var.xres; - if (height > G.scr_var.yres) - height = G.scr_var.yres; -- for (j = 0; j < height; j++) { -+#endif -+ -+ xoffs = yoffs = 0; -+ switch (G.nimage_align % 3) { -+ case 1: xoffs = (G.scr_var.xres - width) / 2; break; -+ case 2: xoffs = G.scr_var.xres - width; break; -+ } -+ xstart = 0; -+ if (xoffs < 0) { -+ xstart = -xoffs; -+ width -= xstart; -+ xoffs = 0; -+ } -+ xoffs *= G.bytes_per_pixel; -+ if (width > G.scr_var.xres) -+ width = G.scr_var.xres; -+ -+ switch (G.nimage_align / 3) { -+ case 1: yoffs = (G.scr_var.yres - height) / 2; break; -+ case 2: yoffs = G.scr_var.yres - height; break; -+ } -+ -+ for (j = 0; j < height && yoffs < G.scr_var.yres; j++, yoffs++) { - unsigned char *pixel; - unsigned char *src; - - if (fread(pixline, 1, line_size, theme_file) != line_size) - bb_error_msg_and_die("bad PPM file '%s'", G.image_filename); -+ -+ if (yoffs < 0) -+ continue; -+ - pixel = pixline; -- src = G.addr + j * G.scr_fix.line_length; -+ src = G.addr + yoffs * G.scr_fix.line_length + xoffs; -+ - for (i = 0; i < width; i++) { - unsigned thispix = fb_pixel_value(pixel[0], pixel[1], pixel[2]); - fb_write_pixel(src, thispix); -@@ -464,9 +510,17 @@ static void fb_drawimage(void) - */ - static void init(const char *cfg_filename) - { -+ static const char align_names[] ALIGN1 = -+ "LT\0" "CT\0" "RT\0" -+ "LM\0" "CM\0" "RM\0" -+ "LB\0" "CB\0" "RB\0"; - static const char param_names[] ALIGN1 = -+ "IMAGE_ALIGN\0" -+ -+ "IMAGE_X\0" "IMAGE_Y\0" - "BAR_WIDTH\0" "BAR_HEIGHT\0" - "BAR_LEFT\0" "BAR_TOP\0" -+ - "BAR_R\0" "BAR_G\0" "BAR_B\0" - #if DEBUG - "DEBUG\0" -@@ -476,14 +530,21 @@ static void init(const char *cfg_filename) - parser_t *parser = config_open2(cfg_filename, xfopen_stdin); - while (config_read(parser, token, 2, 2, "#=", - (PARSE_NORMAL | PARSE_MIN_DIE) & ~(PARSE_TRIM | PARSE_COLLAPSE))) { -- unsigned val = xatoi_positive(token[1]); -+ unsigned val; - int i = index_in_strings(param_names, token[0]); -+ - if (i < 0) - bb_error_msg_and_die("syntax error: %s", token[0]); -- if (i >= 0 && i < 7) -+ -+ if (i <= image_align) -+ val = index_in_strings(align_names, token[1]); -+ else -+ val = xatoi_positive(token[1]); -+ -+ if (i < debug) - G.ns[i] = val; - #if DEBUG -- if (i == 7) { -+ if (i == debug) { - G.bdebug_messages = val; - if (G.bdebug_messages) - G.logfile_fd = xfopen_for_write("/tmp/fbsplash.log"); --- -2.16.2 - diff --git a/legacy/busybox/0009-depmod-support-generating-kmod-binary-index-files.patch b/legacy/busybox/0009-depmod-support-generating-kmod-binary-index-files.patch deleted file mode 100644 index 2034f5c88..000000000 --- a/legacy/busybox/0009-depmod-support-generating-kmod-binary-index-files.patch +++ /dev/null @@ -1,510 +0,0 @@ -From d13cb44f10d730eeac83340f71ea95b6faa0c142 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> -Date: Sun, 25 Oct 2015 22:21:41 +0200 -Subject: [PATCH 09/16] depmod: support generating kmod binary index files - -This allows to use busybox depmod, and run daemons using libkmod (or -even kmod modprobe if needed). - -About +1500 bytes when enabled. This patch merges some depmod code -paths, so when this is disabled it shrinks the code size a little bit. ---- - modutils/Config.src | 9 ++ - modutils/depmod.c | 281 ++++++++++++++++++++++++++++++++++++++++++---------- - modutils/modprobe.c | 15 --- - modutils/modutils.c | 31 ++++++ - modutils/modutils.h | 16 +++ - 5 files changed, 286 insertions(+), 66 deletions(-) - -diff --git a/modutils/Config.src b/modutils/Config.src -index e413702bb..1be7434a5 100644 ---- a/modutils/Config.src -+++ b/modutils/Config.src -@@ -152,6 +152,15 @@ config FEATURE_MODUTILS_ALIAS - - Say Y if unsure. - -+config FEATURE_MODUTILS_BIN -+ bool "Support for the kmod .bin file format" -+ default n -+ depends on DEPMOD && !MODPROBE_SMALL -+ help -+ Generate kmod compatible binary index files for .dep, .alias, -+ .symbols and .builtin files. Allows mixing use of busybox -+ modutils and kmod (binaries and library). -+ - config FEATURE_MODUTILS_SYMBOLS - bool "Support module.symbols file" - default y -diff --git a/modutils/depmod.c b/modutils/depmod.c -index 004c67a11..05c1a9bce 100644 ---- a/modutils/depmod.c -+++ b/modutils/depmod.c -@@ -2,7 +2,7 @@ - /* - * depmod - generate modules.dep - * Copyright (c) 2008 Bernhard Reutner-Fischer -- * Copyrihgt (c) 2008 Timo Teras <timo.teras@iki.fi> -+ * Copyrihgt (c) 2008-2015 Timo Teras <timo.teras@iki.fi> - * Copyright (c) 2008 Vladimir Dronnikov - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. -@@ -26,6 +26,24 @@ - #include "modutils.h" - #include <sys/utsname.h> /* uname() */ - -+#define INDEX_MINCHAR 32 -+#define INDEX_MAXCHAR 128 -+ -+typedef struct index_node { -+ char *prefix; -+ llist_t *values; -+ struct index_node *children[INDEX_MAXCHAR-INDEX_MINCHAR]; -+} index_node; -+ -+struct globals { -+ module_db db; -+ index_node *root_node; -+} FIX_ALIASING; -+#define G (*ptr_to_globals) -+#define INIT_G() do { \ -+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ -+} while (0) -+ - /* - * Theory of operation: - * - iterate over all modules and record their full path -@@ -53,18 +71,12 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA - - for (ptr = image; ptr < image + len - 10; ptr++) { - if (is_prefixed_with(ptr, "depends=")) { -- char *u; -- - ptr += 8; -- for (u = ptr; *u; u++) -- if (*u == '-') -- *u = '_'; -- ptr += string_to_llist(ptr, &e->deps, ","); -+ string_to_llist(replace_underscores(ptr), &e->deps, ","); - } else if (ENABLE_FEATURE_MODUTILS_ALIAS - && is_prefixed_with(ptr, "alias=") - ) { -- llist_add_to(&e->aliases, xstrdup(ptr + 6)); -- ptr += strlen(ptr); -+ llist_add_to(&e->aliases, replace_underscores(xstrdup(ptr + 6))); - } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS - && is_prefixed_with(ptr, "__ksymtab_") - ) { -@@ -74,9 +86,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA - ) { - continue; - } -- llist_add_to(&e->symbols, xstrdup(ptr)); -- ptr += strlen(ptr); -- } -+ llist_add_to(&e->symbols, xasprintf("symbol:%s", ptr)); -+ } else -+ continue; -+ ptr += strlen(ptr); - } - free(image); - -@@ -108,12 +121,6 @@ static void order_dep_list(module_db *modules, module_entry *start, llist_t *add - } - } - --static void xfreopen_write(const char *file, FILE *f) --{ -- if (freopen(file, "w", f) == NULL) -- bb_perror_msg_and_die("can't open '%s'", file); --} -- - //usage:#if !ENABLE_MODPROBE_SMALL - //usage:#define depmod_trivial_usage "[-n] [-b BASE] [VERSION] [MODFILES]..." - //usage:#define depmod_full_usage "\n\n" -@@ -167,6 +174,169 @@ enum { - OPT_C = (1 << 9), /* -C,--config etc_modules_conf: ignored */ - }; - -+/* Support for the mod binary index generation */ -+ -+static void index_init(const char *filename) -+{ -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ index_node *n; -+ -+ n = xzalloc(sizeof(index_node)); -+ n->prefix = xstrdup(""); -+ G.root_node = n; -+ } -+ -+ if (filename && !(option_mask32 & OPT_n)) { -+ if (freopen(filename, "w", stdout) == NULL) -+ bb_perror_msg_and_die("can't open '%s'", filename); -+ } -+} -+ -+static void index_add(const char *key, char *value, const char *prefix) -+{ -+ if (prefix && *prefix) -+ printf("%s%s %s\n", prefix, key, value); -+ else if (prefix) -+ printf("%s\n", value); -+ -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ index_node *cur = G.root_node, *n; -+ unsigned i = 0, j, ch; -+ -+ while (1) { -+ /* Ensure node->prefix is a prefix of &str[i]. -+ * If it is not already, then we must split node. */ -+ for (j = 0; cur->prefix[j]; j++) { -+ ch = cur->prefix[j]; -+ if (ch != key[i+j]) { -+ /* New child is copy of node with prefix[j+1..N] */ -+ n = xzalloc(sizeof(index_node)); -+ n->prefix = xstrdup(&cur->prefix[j+1]); -+ n->values = cur->values; -+ memcpy(n->children, cur->children, sizeof(n->children)); -+ -+ /* Parent has prefix[0..j], child at prefix[j] */ -+ cur->prefix[j] = '\0'; -+ cur->values = NULL; -+ memset(cur->children, 0, sizeof(cur->children)); -+ cur->children[ch-INDEX_MINCHAR] = n; -+ break; -+ } -+ } -+ i += j; -+ -+ ch = key[i]; -+ if (ch == 0) -+ break; -+ -+ if (ch < INDEX_MINCHAR || ch >= INDEX_MAXCHAR) -+ bb_error_msg_and_die("bad module name"); -+ -+ ch -= INDEX_MINCHAR; -+ if (!cur->children[ch]) { -+ n = xzalloc(sizeof(index_node)); -+ cur->children[ch] = n; -+ n->prefix = xstrdup(&key[i+1]); -+ cur = n; -+ break; -+ } -+ -+ /* Descend into child node and continue */ -+ cur = cur->children[ch]; -+ i++; -+ } -+ -+ llist_add_to(&cur->values, value); -+ } -+} -+ -+static uint32_t index_write_node(FILE *out, index_node *n, void (*freeit)(void *data)) -+{ -+ uint32_t child_offs[INDEX_MAXCHAR-INDEX_MINCHAR]; -+ uint32_t offset; -+ uint8_t first = 255, last = 0; -+ unsigned i; -+ -+ for (i = 0; i < INDEX_MAXCHAR-INDEX_MINCHAR; i++) { -+ child_offs[i] = 0; -+ if (!n->children[i]) -+ continue; -+ child_offs[i] = index_write_node(out, n->children[i], freeit); -+ if (first > INDEX_MAXCHAR) -+ first = i; -+ last = i; -+ } -+ -+ offset = ftell(out); -+ -+ if (n->prefix[0]) { -+ fputs(n->prefix, out); -+ fputc('\0', out); -+ offset |= INDEX_NODE_PREFIX; -+ } -+ -+ if (first < INDEX_MAXCHAR) { -+ fputc(first + INDEX_MINCHAR, out); -+ fputc(last + INDEX_MINCHAR, out); -+ fwrite(child_offs + first, sizeof(uint32_t), last - first + 1, out); -+ offset |= INDEX_NODE_CHILDS; -+ } -+ -+ if (n->values) { -+ const llist_t *v; -+ unsigned int cnt; -+ uint32_t u; -+ -+ n->values = llist_rev(n->values); -+ for (v = n->values, cnt = 0; v != NULL; v = v->link, cnt++); -+ u = htonl(cnt); -+ fwrite(&u, sizeof(u), 1, out); -+ for (v = n->values, cnt = 0; v != NULL; v = v->link, cnt++) { -+ u = htonl(cnt); -+ fwrite(&u, sizeof(u), 1, out); -+ fputs(v->data, out); -+ fputc('\0', out); -+ } -+ offset |= INDEX_NODE_VALUES; -+ } -+ -+ llist_free(n->values, freeit); -+ free(n->prefix); -+ free(n); -+ -+ return htonl(offset); -+} -+ -+static void index_dump(const char *filename, int deps_file) -+{ -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ FILE *out; -+ uint32_t header[3] = { -+ htonl(INDEX_MAGIC), -+ htonl(INDEX_VERSION), -+ }; -+ -+ if (option_mask32 & OPT_n) -+ filename = "/dev/null"; -+ else -+ filename = xasprintf("tmp.%s.bin", filename); -+ -+ out = xfopen_for_write(filename); -+ fwrite(header, sizeof(uint32_t), 3, out); -+ header[2] = index_write_node(out, G.root_node, deps_file ? free : 0); -+ rewind(out); -+ G.root_node = NULL; -+ fwrite(header, sizeof(uint32_t), 3, out); -+ if (fclose(out)) { -+ remove(filename); -+ bb_error_msg_and_die(bb_msg_write_error); -+ } -+ /* .bin files are mmap'ed; not renaming it may crash -+ * long standing daemon using libkmod */ -+ rename_or_warn(filename, filename + 4); -+ } -+} -+ - int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int depmod_main(int argc UNUSED_PARAM, char **argv) - { -@@ -178,6 +348,8 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) - unsigned i; - int tmp; - -+ INIT_G(); -+ - getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); - argv += optind; - -@@ -210,53 +382,60 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) - } - - /* Generate dependency and alias files */ -- if (!(option_mask32 & OPT_n)) -- xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout); -- -+ index_init(CONFIG_DEFAULT_DEPMOD_FILE); - moddb_foreach_module(&modules, m, i) { -- printf("%s:", m->name); -- -+ char *buf = xasprintf("%s:", m->name); - order_dep_list(&modules, m, m->deps); -+ - while (m->dnext != m) { - dep = m->dnext; -- printf(" %s", dep->name); -- -+ buf = gather_options_str(buf, dep->name); - /* unlink current entry */ - dep->dnext->dprev = dep->dprev; - dep->dprev->dnext = dep->dnext; - dep->dnext = dep->dprev = dep; - } -- bb_putchar('\n'); -+ index_add(m->modname, buf, ""); - } -- --#if ENABLE_FEATURE_MODUTILS_ALIAS -- if (!(option_mask32 & OPT_n)) -- xfreopen_write("modules.alias", stdout); -- moddb_foreach_module(&modules, m, i) { -- while (m->aliases) { -- /* -- * Last word used to be a basename -- * (filename with path and .ko.* stripped) -- * at the time of module-init-tools 3.4. -- * kmod v.12 uses module name, i.e., s/-/_/g. -- */ -- printf("alias %s %s\n", -- (char*)llist_pop(&m->aliases), -- m->modname); -+ index_dump(CONFIG_DEFAULT_DEPMOD_FILE, 1); -+ -+ if (ENABLE_FEATURE_MODUTILS_ALIAS) { -+ index_init("modules.alias"); -+ moddb_foreach_module(&modules, m, i) { -+ while (m->aliases) { -+ /* -+ * Last word used to be a basename -+ * (filename with path and .ko.* stripped) -+ * at the time of module-init-tools 3.4. -+ * kmod v.12 uses module name, i.e., s/-/_/g. -+ */ -+ index_add((char*)llist_pop(&m->aliases), m->modname, "alias "); -+ } - } -+ index_dump("modules.alias", 0); - } --#endif --#if ENABLE_FEATURE_MODUTILS_SYMBOLS -- if (!(option_mask32 & OPT_n)) -- xfreopen_write("modules.symbols", stdout); -- moddb_foreach_module(&modules, m, i) { -- while (m->symbols) { -- printf("alias symbol:%s %s\n", -- (char*)llist_pop(&m->symbols), -- m->modname); -+ if (ENABLE_FEATURE_MODUTILS_SYMBOLS) { -+ index_init("modules.symbols"); -+ moddb_foreach_module(&modules, m, i) { -+ while (m->symbols) { -+ index_add((char*)llist_pop(&m->symbols), m->modname, "alias "); -+ } -+ } -+ index_dump("modules.symbols", 0); -+ } -+ if (ENABLE_FEATURE_MODUTILS_BIN) { -+ char line[PATH_MAX], modname[MODULE_NAME_LEN]; -+ FILE *in; -+ -+ index_init(NULL); -+ in = xfopen_for_read("modules.builtin"); -+ while (fgets(line, sizeof(line), in) != NULL) { -+ filename2modname(line, modname); -+ index_add(modname, (char *) "", 0); - } -+ fclose(in); -+ index_dump("modules.builtin", 0); - } --#endif - - if (ENABLE_FEATURE_CLEAN_UP) - moddb_free(&modules); -diff --git a/modutils/modprobe.c b/modutils/modprobe.c -index 59f6d54f3..0a398a60f 100644 ---- a/modutils/modprobe.c -+++ b/modutils/modprobe.c -@@ -192,21 +192,6 @@ struct globals { - - static int read_config(const char *path); - --static char *gather_options_str(char *opts, const char *append) --{ -- /* Speed-optimized. We call gather_options_str many times. */ -- if (append) { -- if (opts == NULL) { -- opts = xstrdup(append); -- } else { -- int optlen = strlen(opts); -- opts = xrealloc(opts, optlen + strlen(append) + 2); -- sprintf(opts + optlen, " %s", append); -- } -- } -- return opts; --} -- - static struct module_entry *get_or_add_modentry(const char *module) - { - return moddb_get_or_create(&G.db, module); -diff --git a/modutils/modutils.c b/modutils/modutils.c -index 6f7cd9721..257089af4 100644 ---- a/modutils/modutils.c -+++ b/modutils/modutils.c -@@ -66,6 +66,21 @@ void FAST_FUNC moddb_free(module_db *db) - } - } - -+char * FAST_FUNC gather_options_str(char *opts, const char *append) -+{ -+ /* Speed-optimized. We call gather_options_str many times. */ -+ if (append) { -+ if (opts == NULL) { -+ opts = xstrdup(append); -+ } else { -+ int optlen = strlen(opts); -+ opts = xrealloc(opts, optlen + strlen(append) + 2); -+ sprintf(opts + optlen, " %s", append); -+ } -+ } -+ return opts; -+} -+ - void FAST_FUNC replace(char *s, char what, char with) - { - while (*s) { -@@ -75,6 +90,22 @@ void FAST_FUNC replace(char *s, char what, char with) - } - } - -+char* FAST_FUNC replace_underscores(char *s) -+{ -+ int i; -+ for (i = 0; s[i]; i++) { -+ switch (s[i]) { -+ case '-': -+ s[i] = '_'; -+ break; -+ case '[': -+ i += strcspn(&s[i], "]"); -+ break; -+ } -+ } -+ return s; -+} -+ - int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) - { - char *tok; -diff --git a/modutils/modutils.h b/modutils/modutils.h -index 4a702e97c..73e816028 100644 ---- a/modutils/modutils.h -+++ b/modutils/modutils.h -@@ -18,6 +18,20 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN - #define MODULE_NAME_LEN 256 - #define MODULE_HASH_SIZE 256 - -+/* .bin index format definitions */ -+#define INDEX_MAGIC 0xB007F457 -+#define INDEX_VERSION_MAJOR 0x0002 -+#define INDEX_VERSION_MINOR 0x0001 -+#define INDEX_VERSION ((INDEX_VERSION_MAJOR<<16)|INDEX_VERSION_MINOR) -+ -+enum node_offset { -+ INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */ -+ INDEX_NODE_PREFIX = 0x80000000, -+ INDEX_NODE_VALUES = 0x40000000, -+ INDEX_NODE_CHILDS = 0x20000000, -+ INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */ -+}; -+ - typedef struct module_entry { - struct module_entry *next; - char *name, *modname; -@@ -47,7 +61,9 @@ module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC; - module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC; - void moddb_free(module_db *db) FAST_FUNC; - -+char *gather_options_str(char *opts, const char *append) FAST_FUNC; - void replace(char *s, char what, char with) FAST_FUNC; -+char *replace_underscores(char *s) FAST_FUNC; - int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC; - char *filename2modname(const char *filename, char *modname) FAST_FUNC; - #if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS --- -2.16.2 - diff --git a/legacy/busybox/0009-sysklogd-add-Z-option-to-adjust-message-timezones.patch b/legacy/busybox/0009-sysklogd-add-Z-option-to-adjust-message-timezones.patch deleted file mode 100644 index 2624675c4..000000000 --- a/legacy/busybox/0009-sysklogd-add-Z-option-to-adjust-message-timezones.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 1cb2e911c47f1b798ee610deabbea21ba6fb6961 Mon Sep 17 00:00:00 2001 -From: Shiz <hi@shiz.me> -Date: Mon, 8 May 2017 23:09:13 +0200 -Subject: [PATCH 09/11] sysklogd: add -Z option to adjust message timezones - -Some syslog() implementations like musl's[1] always send timestamps in UTC. -This change adds a new option to syslogd, -Z, to assume incoming timestamps -are always UTC and adjust them to the local timezone (of the syslogd) before -logging. - -[1]: http://www.openwall.com/lists/musl/2014/01/29/1 - -Signed-off-by: Shiz <hi@shiz.me> ---- - sysklogd/syslogd.c | 23 +++++++++++++++++++---- - 1 file changed, 19 insertions(+), 4 deletions(-) - -diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c -index d64ff278f..159336ed7 100644 ---- a/sysklogd/syslogd.c -+++ b/sysklogd/syslogd.c -@@ -122,6 +122,7 @@ - //usage: "(this version of syslogd ignores /etc/syslog.conf)\n" - //usage: ) - //usage: "\n -n Run in foreground" -+//usage: "\n -Z Adjust incoming UTC times to local time" - //usage: IF_FEATURE_REMOTE_LOG( - //usage: "\n -R HOST[:PORT] Log to HOST:PORT (default PORT:514)" - //usage: "\n -L Log locally and via network (default is network only if -R)" -@@ -233,6 +234,8 @@ typedef struct logRule_t { - /*int markInterval;*/ \ - /* level of messages to be logged */ \ - int logLevel; \ -+ /* whether to adjust message timezone */\ -+ int adjustTimezone; \ - IF_FEATURE_ROTATE_LOGFILE( \ - /* max size of file before rotation */ \ - unsigned logFileSize; \ -@@ -316,6 +319,7 @@ enum { - OPTBIT_outfile, // -O - OPTBIT_loglevel, // -l - OPTBIT_small, // -S -+ OPTBIT_adjusttz, // -Z - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize ,) // -s - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt ,) // -b - IF_FEATURE_REMOTE_LOG( OPTBIT_remotelog ,) // -R -@@ -330,6 +334,7 @@ enum { - OPT_outfile = 1 << OPTBIT_outfile , - OPT_loglevel = 1 << OPTBIT_loglevel, - OPT_small = 1 << OPTBIT_small , -+ OPT_adjusttz = 1 << OPTBIT_adjusttz, - OPT_filesize = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize )) + 0, - OPT_rotatecnt = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt )) + 0, - OPT_remotelog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_remotelog )) + 0, -@@ -339,7 +344,7 @@ enum { - OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, - OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, - }; --#define OPTION_STR "m:nO:l:S" \ -+#define OPTION_STR "m:nO:l:SZ" \ - IF_FEATURE_ROTATE_LOGFILE("s:" ) \ - IF_FEATURE_ROTATE_LOGFILE("b:" ) \ - IF_FEATURE_REMOTE_LOG( "R:*") \ -@@ -815,17 +820,23 @@ static void timestamp_and_log(int pri, char *msg, int len) - { - char *timestamp; - time_t now; -+ struct tm nowtm = { .tm_isdst = 0 }; - - /* Jan 18 00:11:22 msg... */ - /* 01234567890123456 */ - if (len < 16 || msg[3] != ' ' || msg[6] != ' ' - || msg[9] != ':' || msg[12] != ':' || msg[15] != ' ' - ) { -- time(&now); -+ now = time(NULL); - timestamp = ctime(&now) + 4; /* skip day of week */ - } else { -- now = 0; -- timestamp = msg; -+ if (G.adjustTimezone && strptime(msg, "%b %e %T", &nowtm)) { -+ now = mktime(&nowtm) - timezone; -+ timestamp = ctime(&now) + 4; /* skip day of week */ -+ } else { -+ now = 0; -+ timestamp = msg; -+ } - msg += 16; - } - timestamp[15] = '\0'; -@@ -1130,6 +1141,10 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv) - if (opts & OPT_loglevel) // -l - G.logLevel = xatou_range(opt_l, 1, 8); - //if (opts & OPT_small) // -S -+ if (opts & OPT_adjusttz) { // -Z -+ G.adjustTimezone = 1; -+ tzset(); -+ } - #if ENABLE_FEATURE_ROTATE_LOGFILE - if (opts & OPT_filesize) // -s - G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; --- -2.13.2 - diff --git a/legacy/busybox/0010-Add-flag-for-not-following-symlinks-when-recursing.patch b/legacy/busybox/0010-Add-flag-for-not-following-symlinks-when-recursing.patch deleted file mode 100644 index a45c46d09..000000000 --- a/legacy/busybox/0010-Add-flag-for-not-following-symlinks-when-recursing.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 1c8c2316f98c2e4894c4c1686f0aa7937fcc0a17 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Fri, 25 Jul 2014 15:28:33 +0200 -Subject: [PATCH 10/16] Add flag for not following symlinks when recursing - -function old new delta -.rodata 7934 7967 +33 -diff_longopts 253 270 +17 -packed_usage 1704 1720 +16 -diff_main 1665 1662 -3 ------------------------------------------------------------------------------- -(add/remove: 0/0 grow/shrink: 3/1 up/down: 66/-3) Total: 63 bytes ---- - editors/diff.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/editors/diff.c b/editors/diff.c -index 1462a9b18..2c899578e 100644 ---- a/editors/diff.c -+++ b/editors/diff.c -@@ -113,6 +113,9 @@ - //usage: "\n -N Treat absent files as empty" - //usage: "\n -q Output only whether files differ" - //usage: "\n -r Recurse" -+//usage: IF_LONG_OPTS( -+//usage: "\n --no-dereference Don't follow symlinks" -+//usage: ) - //usage: "\n -S Start with FILE when comparing directories" - //usage: "\n -T Make tabs line up by prefixing a tab when necessary" - //usage: "\n -s Report when two files are the same" -@@ -154,6 +157,7 @@ enum { /* Commandline flags */ - FLAG_p, /* not implemented */ - FLAG_B, - FLAG_E, /* not implemented */ -+ FLAG_no_deref, - }; - #define FLAG(x) (1 << FLAG_##x) - -@@ -867,7 +871,8 @@ static void diffdir(char *p[2], const char *s_start) - * Using list.len to specify its length, - * add_to_dirlist will remove it. */ - list[i].len = strlen(p[i]); -- recursive_action(p[i], ACTION_RECURSE | ACTION_FOLLOWLINKS, -+ recursive_action(p[i], ACTION_RECURSE | -+ ((option_mask32 & FLAG(no_deref)) ? 0 : ACTION_FOLLOWLINKS), - add_to_dirlist, skip_dir, &list[i], 0); - /* Sort dl alphabetically. - * GNU diff does this ignoring any number of trailing dots. -@@ -964,6 +969,7 @@ static const char diff_longopts[] ALIGN1 = - "report-identical-files\0" No_argument "s" - "starting-file\0" Required_argument "S" - "minimal\0" No_argument "d" -+ "no-dereference\0" No_argument "\xff" - ; - # define GETOPT32 getopt32long - # define LONGOPTS ,diff_longopts --- -2.16.2 - diff --git a/legacy/busybox/0010-udhcpc-Don-t-background-if-n-is-given.patch b/legacy/busybox/0010-udhcpc-Don-t-background-if-n-is-given.patch deleted file mode 100644 index 75fe62dfd..000000000 --- a/legacy/busybox/0010-udhcpc-Don-t-background-if-n-is-given.patch +++ /dev/null @@ -1,45 +0,0 @@ -From a663349a9ae6d62bfad1243a8781fb254065b480 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 6 Jul 2017 13:39:15 +0200 -Subject: [PATCH 10/11] udhcpc: Don't background if -n is given - -we need add -b to our udhcpc options to prevent boot forever if there are no -dhcp server. We also need a way for users to disable this behavior by making -it possible to set -n option at runtime. ---- - networking/udhcp/dhcpc.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c -index 43aac1b85..bf53dd559 100644 ---- a/networking/udhcp/dhcpc.c -+++ b/networking/udhcp/dhcpc.c -@@ -1504,19 +1504,19 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) - } - leasefail: - udhcp_run_script(NULL, "leasefail"); -+ if (opt & OPT_n) { /* abort if no lease */ -+ bb_error_msg("no lease, failing"); -+ retval = 1; -+ goto ret; -+ } - #if BB_MMU /* -b is not supported on NOMMU */ - if (opt & OPT_b) { /* background if no lease */ - bb_error_msg("no lease, forking to background"); - client_background(); - /* do not background again! */ - opt = ((opt & ~OPT_b) | OPT_f); -- } else --#endif -- if (opt & OPT_n) { /* abort if no lease */ -- bb_error_msg("no lease, failing"); -- retval = 1; -- goto ret; - } -+#endif - /* wait before trying again */ - timeout = tryagain_timeout; - packet_num = 0; --- -2.13.2 - diff --git a/legacy/busybox/0011-sysklogd-add-Z-option-to-adjust-message-timezones.patch b/legacy/busybox/0011-sysklogd-add-Z-option-to-adjust-message-timezones.patch deleted file mode 100644 index b4ba240c4..000000000 --- a/legacy/busybox/0011-sysklogd-add-Z-option-to-adjust-message-timezones.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 889a08dc0ae0d6b76692e6ed811f431c5b5db53c Mon Sep 17 00:00:00 2001 -From: Shiz <hi@shiz.me> -Date: Mon, 8 May 2017 23:09:13 +0200 -Subject: [PATCH 11/16] sysklogd: add -Z option to adjust message timezones - -Some syslog() implementations like musl's[1] always send timestamps in UTC. -This change adds a new option to syslogd, -Z, to assume incoming timestamps -are always UTC and adjust them to the local timezone (of the syslogd) before -logging. - -[1]: http://www.openwall.com/lists/musl/2014/01/29/1 - -Signed-off-by: Shiz <hi@shiz.me> ---- - sysklogd/syslogd.c | 23 +++++++++++++++++++---- - 1 file changed, 19 insertions(+), 4 deletions(-) - -diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c -index 4265f4f90..eca955891 100644 ---- a/sysklogd/syslogd.c -+++ b/sysklogd/syslogd.c -@@ -122,6 +122,7 @@ - //usage: "(this version of syslogd ignores /etc/syslog.conf)\n" - //usage: ) - //usage: "\n -n Run in foreground" -+//usage: "\n -Z Adjust incoming UTC times to local time" - //usage: IF_FEATURE_REMOTE_LOG( - //usage: "\n -R HOST[:PORT] Log to HOST:PORT (default PORT:514)" - //usage: "\n -L Log locally and via network (default is network only if -R)" -@@ -233,6 +234,8 @@ typedef struct logRule_t { - /*int markInterval;*/ \ - /* level of messages to be logged */ \ - int logLevel; \ -+ /* whether to adjust message timezone */\ -+ int adjustTimezone; \ - IF_FEATURE_ROTATE_LOGFILE( \ - /* max size of file before rotation */ \ - unsigned logFileSize; \ -@@ -316,6 +319,7 @@ enum { - OPTBIT_outfile, // -O - OPTBIT_loglevel, // -l - OPTBIT_small, // -S -+ OPTBIT_adjusttz, // -Z - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize ,) // -s - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt ,) // -b - IF_FEATURE_REMOTE_LOG( OPTBIT_remotelog ,) // -R -@@ -330,6 +334,7 @@ enum { - OPT_outfile = 1 << OPTBIT_outfile , - OPT_loglevel = 1 << OPTBIT_loglevel, - OPT_small = 1 << OPTBIT_small , -+ OPT_adjusttz = 1 << OPTBIT_adjusttz, - OPT_filesize = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize )) + 0, - OPT_rotatecnt = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt )) + 0, - OPT_remotelog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_remotelog )) + 0, -@@ -339,7 +344,7 @@ enum { - OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, - OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, - }; --#define OPTION_STR "m:nO:l:S" \ -+#define OPTION_STR "m:nO:l:SZ" \ - IF_FEATURE_ROTATE_LOGFILE("s:" ) \ - IF_FEATURE_ROTATE_LOGFILE("b:" ) \ - IF_FEATURE_REMOTE_LOG( "R:*") \ -@@ -815,17 +820,23 @@ static void timestamp_and_log(int pri, char *msg, int len) - { - char *timestamp; - time_t now; -+ struct tm nowtm = { .tm_isdst = 0 }; - - /* Jan 18 00:11:22 msg... */ - /* 01234567890123456 */ - if (len < 16 || msg[3] != ' ' || msg[6] != ' ' - || msg[9] != ':' || msg[12] != ':' || msg[15] != ' ' - ) { -- time(&now); -+ now = time(NULL); - timestamp = ctime(&now) + 4; /* skip day of week */ - } else { -- now = 0; -- timestamp = msg; -+ if (G.adjustTimezone && strptime(msg, "%b %e %T", &nowtm)) { -+ now = mktime(&nowtm) - timezone; -+ timestamp = ctime(&now) + 4; /* skip day of week */ -+ } else { -+ now = 0; -+ timestamp = msg; -+ } - msg += 16; - } - timestamp[15] = '\0'; -@@ -1129,6 +1140,10 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv) - if (opts & OPT_loglevel) // -l - G.logLevel = xatou_range(opt_l, 1, 8); - //if (opts & OPT_small) // -S -+ if (opts & OPT_adjusttz) { // -Z -+ G.adjustTimezone = 1; -+ tzset(); -+ } - #if ENABLE_FEATURE_ROTATE_LOGFILE - if (opts & OPT_filesize) // -s - G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; --- -2.16.2 - diff --git a/legacy/busybox/0011-testsuite-fix-cpio-tests.patch b/legacy/busybox/0011-testsuite-fix-cpio-tests.patch deleted file mode 100644 index a6eb803de..000000000 --- a/legacy/busybox/0011-testsuite-fix-cpio-tests.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 9a522cf388e321b47f9462bbbd7726323095f8db Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 6 Jul 2017 13:41:32 +0200 -Subject: [PATCH 11/11] testsuite: fix cpio tests - -The cpio tests don't search for the right output line correctly, -using a hardcoded tail offset. Instead, grep for the file entry -just added. - -The reverse-hunk patch tests seem to get the output order wrong, -and the tests pass when this is corrected. ---- - testsuite/cpio.tests | 6 +++--- - testsuite/patch.tests | 4 ++-- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests -index 88ec086b6..40f72c363 100755 ---- a/testsuite/cpio.tests -+++ b/testsuite/cpio.tests -@@ -129,7 +129,7 @@ SKIP= - - optional FEATURE_CPIO_O - testing "cpio uses by default uid/gid" \ --"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ -+"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | grep -F $(basename $0) | awk ' { print \$2 } '; echo \$?" \ - "\ - $user/$group - 0 -@@ -138,7 +138,7 @@ SKIP= - - optional FEATURE_CPIO_O - testing "cpio -R with create" \ --"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ -+"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | grep -F $(basename $0) | awk ' { print \$2 } '; echo \$?" \ - "\ - 1234/5678 - 0 -@@ -147,7 +147,7 @@ SKIP= - - optional FEATURE_CPIO_O - testing "cpio -R with extract" \ --"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ -+"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | grep -F $(basename $0) | awk ' { print \$2 } '; echo \$?" \ - "\ - 8765/4321 - 0 -diff --git a/testsuite/patch.tests b/testsuite/patch.tests -index 39205242c..1d48e90be 100755 ---- a/testsuite/patch.tests -+++ b/testsuite/patch.tests -@@ -75,12 +75,12 @@ zxc - testing "patch detects already applied hunk" \ - 'patch 2>&1; echo $?; cat input' \ - "\ -+patching file input - Possibly reversed hunk 1 at 4 - Hunk 1 FAILED 1/1. - abc - +def - 123 --patching file input - 1 - abc - def -@@ -103,12 +103,12 @@ def - testing "patch detects already applied hunk at the EOF" \ - 'patch 2>&1; echo $?; cat input' \ - "\ -+patching file input - Possibly reversed hunk 1 at 4 - Hunk 1 FAILED 1/1. - abc - 123 - +456 --patching file input - 1 - abc - 123 --- -2.13.2 - diff --git a/legacy/busybox/0012-microcom-segfault.patch b/legacy/busybox/0012-microcom-segfault.patch deleted file mode 100644 index 4789079b3..000000000 --- a/legacy/busybox/0012-microcom-segfault.patch +++ /dev/null @@ -1,31 +0,0 @@ -From fd8a0116a29ea4014fac7fbdba2636fc7b51ffc2 Mon Sep 17 00:00:00 2001 -From: Marian Buschsieweke <marian.buschsieweke@ovgu.de> -Date: Wed, 2 Aug 2017 23:36:08 +0200 -Subject: [PATCH] miscutils/microcom: Fixed segfault - -microcom did not check if required parameter TTY is present. Thus, -bb_basename() was called with a NULL pointer if TTY was missing. -This commit adds the missing check. ---- - miscutils/microcom.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/miscutils/microcom.c b/miscutils/microcom.c -index 14b9f3baf..38f6425c1 100644 ---- a/miscutils/microcom.c -+++ b/miscutils/microcom.c -@@ -78,6 +78,11 @@ int microcom_main(int argc UNUSED_PARAM, char **argv) - // argc -= optind; - argv += optind; - -+ if (*argv == NULL){ -+ bb_show_usage(); -+ return EXIT_FAILURE; -+ } -+ - // try to create lock file in /var/lock - device_lock_file = (char *)bb_basename(argv[0]); - device_lock_file = xasprintf("/var/lock/LCK..%s", device_lock_file); --- -2.13.3 - diff --git a/legacy/busybox/0012-udhcpc-Don-t-background-if-n-is-given.patch b/legacy/busybox/0012-udhcpc-Don-t-background-if-n-is-given.patch deleted file mode 100644 index 50719b003..000000000 --- a/legacy/busybox/0012-udhcpc-Don-t-background-if-n-is-given.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 7f3d0620051c30e2047593092aa054565756b57f Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 6 Jul 2017 13:39:15 +0200 -Subject: [PATCH 12/16] udhcpc: Don't background if -n is given - -we need add -b to our udhcpc options to prevent boot forever if there are no -dhcp server. We also need a way for users to disable this behavior by making -it possible to set -n option at runtime. ---- - networking/udhcp/dhcpc.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c -index cc1d22c8e..10b846b0a 100644 ---- a/networking/udhcp/dhcpc.c -+++ b/networking/udhcp/dhcpc.c -@@ -1479,19 +1479,19 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) - } - leasefail: - udhcp_run_script(NULL, "leasefail"); -+ if (opt & OPT_n) { /* abort if no lease */ -+ bb_error_msg("no lease, failing"); -+ retval = 1; -+ goto ret; -+ } - #if BB_MMU /* -b is not supported on NOMMU */ - if (opt & OPT_b) { /* background if no lease */ - bb_error_msg("no lease, forking to background"); - client_background(); - /* do not background again! */ - opt = ((opt & ~OPT_b) | OPT_f); -- } else --#endif -- if (opt & OPT_n) { /* abort if no lease */ -- bb_error_msg("no lease, failing"); -- retval = 1; -- goto ret; - } -+#endif - /* wait before trying again */ - timeout = tryagain_timeout; - packet_num = 0; --- -2.16.2 - diff --git a/legacy/busybox/0013-testsuite-fix-cpio-tests.patch b/legacy/busybox/0013-testsuite-fix-cpio-tests.patch deleted file mode 100644 index a9ba0c4d0..000000000 --- a/legacy/busybox/0013-testsuite-fix-cpio-tests.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 495a53387a12bffe393dcd0d6de2bc64374d38d2 Mon Sep 17 00:00:00 2001 -From: Natanael Copa <ncopa@alpinelinux.org> -Date: Thu, 6 Jul 2017 13:41:32 +0200 -Subject: [PATCH 13/16] testsuite: fix cpio tests - -The cpio tests don't search for the right output line correctly, -using a hardcoded tail offset. Instead, grep for the file entry -just added. - -The reverse-hunk patch tests seem to get the output order wrong, -and the tests pass when this is corrected. ---- - testsuite/cpio.tests | 6 +++--- - testsuite/patch.tests | 4 ++-- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests -index 88ec086b6..40f72c363 100755 ---- a/testsuite/cpio.tests -+++ b/testsuite/cpio.tests -@@ -129,7 +129,7 @@ SKIP= - - optional FEATURE_CPIO_O - testing "cpio uses by default uid/gid" \ --"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ -+"echo $0 | cpio -o -H newc | cpio -tv 2>&1 | grep -F $(basename $0) | awk ' { print \$2 } '; echo \$?" \ - "\ - $user/$group - 0 -@@ -138,7 +138,7 @@ SKIP= - - optional FEATURE_CPIO_O - testing "cpio -R with create" \ --"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ -+"echo $0 | cpio -o -H newc -R 1234:5678 | cpio -tv 2>&1 | grep -F $(basename $0) | awk ' { print \$2 } '; echo \$?" \ - "\ - 1234/5678 - 0 -@@ -147,7 +147,7 @@ SKIP= - - optional FEATURE_CPIO_O - testing "cpio -R with extract" \ --"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | tail -n +2 | awk ' { print \$2 } '; echo \$?" \ -+"echo $0 | cpio -o -H newc | cpio -tv -R 8765:4321 2>&1 | grep -F $(basename $0) | awk ' { print \$2 } '; echo \$?" \ - "\ - 8765/4321 - 0 -diff --git a/testsuite/patch.tests b/testsuite/patch.tests -index 39205242c..1d48e90be 100755 ---- a/testsuite/patch.tests -+++ b/testsuite/patch.tests -@@ -75,12 +75,12 @@ zxc - testing "patch detects already applied hunk" \ - 'patch 2>&1; echo $?; cat input' \ - "\ -+patching file input - Possibly reversed hunk 1 at 4 - Hunk 1 FAILED 1/1. - abc - +def - 123 --patching file input - 1 - abc - def -@@ -103,12 +103,12 @@ def - testing "patch detects already applied hunk at the EOF" \ - 'patch 2>&1; echo $?; cat input' \ - "\ -+patching file input - Possibly reversed hunk 1 at 4 - Hunk 1 FAILED 1/1. - abc - 123 - +456 --patching file input - 1 - abc - 123 --- -2.16.2 - diff --git a/legacy/busybox/0014-miscutils-microcom-Fixed-segfault.patch b/legacy/busybox/0014-miscutils-microcom-Fixed-segfault.patch deleted file mode 100644 index 59114460a..000000000 --- a/legacy/busybox/0014-miscutils-microcom-Fixed-segfault.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 2881266313824ed1c2d422ea905e25509f9bc924 Mon Sep 17 00:00:00 2001 -From: Marian Buschsieweke <marian.buschsieweke@ovgu.de> -Date: Wed, 2 Aug 2017 23:36:08 +0200 -Subject: [PATCH 14/16] miscutils/microcom: Fixed segfault - -microcom did not check if required parameter TTY is present. Thus, -bb_basename() was called with a NULL pointer if TTY was missing. -This commit adds the missing check. ---- - miscutils/microcom.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/miscutils/microcom.c b/miscutils/microcom.c -index fa090057e..96ea02b16 100644 ---- a/miscutils/microcom.c -+++ b/miscutils/microcom.c -@@ -76,6 +76,11 @@ int microcom_main(int argc UNUSED_PARAM, char **argv) - // argc -= optind; - argv += optind; - -+ if (*argv == NULL){ -+ bb_show_usage(); -+ return EXIT_FAILURE; -+ } -+ - // try to create lock file in /var/lock - device_lock_file = (char *)bb_basename(argv[0]); - device_lock_file = xasprintf("/var/lock/LCK..%s", device_lock_file); --- -2.16.2 - diff --git a/legacy/busybox/0015-ash-introduce-a-config-option-to-search-current-dire.patch b/legacy/busybox/0015-ash-introduce-a-config-option-to-search-current-dire.patch deleted file mode 100644 index 9fc6f7e68..000000000 --- a/legacy/busybox/0015-ash-introduce-a-config-option-to-search-current-dire.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 13c7e0cc7767b84e183ddbc3400171874478bf06 Mon Sep 17 00:00:00 2001 -From: Denys Vlasenko <vda.linux@googlemail.com> -Date: Fri, 26 Jan 2018 15:15:43 +0100 -Subject: [PATCH 15/16] ash: introduce a config option to search current - directory for sourced files - ---- - shell/ash.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/shell/ash.c b/shell/ash.c -index d04096a9b..5dd184360 100644 ---- a/shell/ash.c -+++ b/shell/ash.c -@@ -132,6 +132,13 @@ - //config: you to run the specified command or builtin, - //config: even when there is a function with the same name. - //config: -+//config:config ASH_BASH_SOURCE_CURDIR -+//config: bool "'source' and '.' builtins search current directory after $PATH" -+//config: default n # do not encourage non-standard behavior -+//config: depends ASH_BASH_COMPAT -+//config: help -+//config: This is not compliant with standards. Avoid if possible. -+//config: - //config:config ASH_COMMAND_NOT_FOUND_HOOK - //config: bool "command_not_found_handle hook support" - //config: default y -@@ -12919,10 +12926,14 @@ find_dot_file(char *name) - if (fullname != name) - stunalloc(fullname); - } -+ /* not found in PATH */ - -- /* not found in the PATH */ -+#if ENABLE_ASH_BASH_SOURCE_CURDIR -+ return name; -+#else - ash_msg_and_raise_error("%s: not found", name); - /* NOTREACHED */ -+#endif - } - - static int FAST_FUNC --- -2.16.2 - diff --git a/legacy/busybox/0016-top-handle-much-larger-VSZ-values.patch b/legacy/busybox/0016-top-handle-much-larger-VSZ-values.patch deleted file mode 100644 index c8013403f..000000000 --- a/legacy/busybox/0016-top-handle-much-larger-VSZ-values.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 9d37e0e491d53e71c2e3ede1e002790e1026b9c6 Mon Sep 17 00:00:00 2001 -From: Denys Vlasenko <vda.linux@googlemail.com> -Date: Wed, 7 Mar 2018 03:59:52 +0100 -Subject: [PATCH 16/16] top: handle much larger VSZ values - -function old new delta -display_process_list 1018 999 -19 - -Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> ---- - procps/top.c | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/procps/top.c b/procps/top.c -index b777c494e..9bb3eed29 100644 ---- a/procps/top.c -+++ b/procps/top.c -@@ -607,7 +607,6 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) - }; - - top_status_t *s; -- char vsz_str_buf[8]; - unsigned long total_memory = display_header(scr_width, &lines_rem); /* or use total_vsz? */ - /* xxx_shift and xxx_scale variables allow us to replace - * expensive divides with multiply and shift */ -@@ -688,19 +687,18 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) - lines_rem = ntop - G_scroll_ofs; - s = top + G_scroll_ofs; - while (--lines_rem >= 0) { -+ char vsz_str_buf[8]; - unsigned col; -+ - CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); - #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE - CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); - #endif - -- if (s->vsz >= 100000) -- sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); -- else -- sprintf(vsz_str_buf, "%7lu", s->vsz); -+ smart_ulltoa5(s->vsz, vsz_str_buf, " mgtpezy"); - /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ - col = snprintf(line_buf, scr_width, -- "\n" "%5u%6u %-8.8s %s%s" FMT -+ "\n" "%5u%6u %-8.8s %s %.5s" FMT - IF_FEATURE_TOP_SMP_PROCESS(" %3d") - IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT) - " ", -@@ -710,7 +708,7 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) - IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) - IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) - ); -- if ((int)(col + 1) < scr_width) -+ if ((int)(scr_width - col) > 1) - read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm); - fputs(line_buf, stdout); - /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, --- -2.16.2 - diff --git a/legacy/busybox/0017-ifupdown-do-not-fail-if-interface-disappears-during-.patch b/legacy/busybox/0017-ifupdown-do-not-fail-if-interface-disappears-during-.patch deleted file mode 100644 index bdf24b783..000000000 --- a/legacy/busybox/0017-ifupdown-do-not-fail-if-interface-disappears-during-.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 444a2f6be54186ae9ade1f2c3d4356cd62a720c5 Mon Sep 17 00:00:00 2001 -From: Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> -Date: Fri, 23 Mar 2018 14:56:52 +0200 -Subject: [PATCH] ifupdown: do not fail if interface disappears during ifdown - -Interface may not exist because it got deleted by an ifdown hook script -earlier. This may happen when a virtual interface, such as VLAN, has multiple -iface blocks defined. - -Signed-off-by: Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> ---- - networking/ifupdown.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/networking/ifupdown.c b/networking/ifupdown.c -index 534c9f0c7..35d13c5e1 100644 ---- a/networking/ifupdown.c -+++ b/networking/ifupdown.c -@@ -141,6 +141,7 @@ - #include "libbb.h" - #include "common_bufsiz.h" - /* After libbb.h, since it needs sys/types.h on some systems */ -+#include <net/if.h> - #include <sys/utsname.h> - #include <fnmatch.h> - -@@ -503,6 +504,7 @@ static int FAST_FUNC static_up6(struct interface_defn_t *ifd, execfn *exec) - - static int FAST_FUNC static_down6(struct interface_defn_t *ifd, execfn *exec) - { -+ if (!if_nametoindex(ifd->iface)) return 1; - # if ENABLE_FEATURE_IFUPDOWN_IP - return execute("ip link set %iface% down", ifd, exec); - # else -@@ -598,6 +600,7 @@ static int FAST_FUNC static_up(struct interface_defn_t *ifd, execfn *exec) - static int FAST_FUNC static_down(struct interface_defn_t *ifd, execfn *exec) - { - int result; -+ if (!if_nametoindex(ifd->iface)) return 2; - # if ENABLE_FEATURE_IFUPDOWN_IP - /* Optional "label LBL" is necessary if interface is an alias (eth0:0), - * otherwise "ip addr flush dev eth0:0" flushes all addresses on eth0. --- -2.14.3 - diff --git a/legacy/busybox/APKBUILD b/legacy/busybox/APKBUILD deleted file mode 100644 index 44b3e352d..000000000 --- a/legacy/busybox/APKBUILD +++ /dev/null @@ -1,223 +0,0 @@ -# Contributor: Łukasz Jendrysik <scadu@yandex.com> -# Contributor: Oliver Smith <ollieparanoid@bitmessage.ch> -# Maintainer: -pkgname=busybox -pkgver=1.28.4 -pkgrel=2 -pkgdesc="Size optimized toolbox of many common UNIX utilities" -url="https://busybox.net" -arch="all" -license="GPL-2.0-only AND GPL-2.0+" -makedepends_build="openssl-dev" -makedepends_host="linux-headers" -makedepends="$makedepends_build $makedepends_host" -checkdepends="zip" -provides="/sbin/init" -install="$pkgname.post-install $pkgname.post-upgrade $pkgname.pre-deinstall - $pkgname-extras.post-install $pkgname-extras.pre-deinstall" -subpackages="$pkgname-static $pkgname-suid $pkgname-extras $pkgname-binsh" -options="suid !check" -triggers="busybox.trigger=/bin:/usr/bin:/sbin:/usr/sbin:/lib/modules/*" -source="http://busybox.net/downloads/$pkgname-$pkgver.tar.bz2 - 0001-ash-add-support-for-command_not_found_handle-hook-fu.patch - 0002-fsck-resolve-LABEL-.-UUID-.-spec-to-device.patch - 0003-ash-exec-busybox.static.patch - 0004-app-location-for-cpio-vi-and-lspci.patch - 0005-udhcpc-set-default-discover-retries-to-5.patch - 0006-ping-make-ping-work-without-root-privileges.patch - 0007-fbsplash-support-console-switching.patch - 0008-fbsplash-support-image-and-bar-alignment-and-positio.patch - 0009-depmod-support-generating-kmod-binary-index-files.patch - 0010-Add-flag-for-not-following-symlinks-when-recursing.patch - 0011-sysklogd-add-Z-option-to-adjust-message-timezones.patch - 0012-udhcpc-Don-t-background-if-n-is-given.patch - 0013-testsuite-fix-cpio-tests.patch - 0014-miscutils-microcom-Fixed-segfault.patch - 0015-ash-introduce-a-config-option-to-search-current-dire.patch - 0016-top-handle-much-larger-VSZ-values.patch - 0017-ifupdown-do-not-fail-if-interface-disappears-during-.patch - - 0001-cat-fix-cat-e-and-cat-v-erroneously-numbering-1st-li.patch - - 0001-wget-emit-a-message-that-certificate-verification-is.patch - - acpid.logrotate - busyboxconfig - busyboxconfig-extras - bbsuid.c - dad.if-up - nologin.c - " - -# secfixes: -# 1.27.2-r4: -# - CVE-2017-16544 -# - CVE-2017-15873 -# - CVE-2017-15874 - -builddir="$srcdir"/$pkgname-$pkgver - -_staticdir="$srcdir"/build-static -_dyndir="$srcdir"/build-dynamic -_dyndir_extras="$srcdir"/build-dynamic-extras -_config="$srcdir"/busyboxconfig -_config_extras="$srcdir"/busyboxconfig-extras - -prepare() { - default_prepare - - cd "$builddir" - mkdir -p "$_staticdir" "$_dyndir" "$_dyndir_extras" - cp "$srcdir"/nologin.c loginutils/ -} - -build() { - # build bbsuid - msg "Building bbsuid" - ${CC:-${CROSS_COMPILE}gcc} ${CPPFLAGS} ${CFLAGS} \ - ${LDFLAGS} "$srcdir"/bbsuid.c -o "$_dyndir"/bbsuid - - # build dynamic - cd "$_dyndir" - msg "Building dynamic busybox" - cp "$_config" .config - [ "$CLIBC" = musl ] && sed -i \ - -e "s/CONFIG_EXTRA_COMPAT=y/CONFIG_EXTRA_COMPAT=n/" \ - .config - make -C "$builddir" O="$PWD" silentoldconfig - make - - # build dynamic (extras) - cd "$_dyndir_extras" - msg "Building dynamic busybox-extras" - cp "$_config_extras" .config - [ "$CLIBC" = musl ] && sed -i \ - -e "s/CONFIG_EXTRA_COMPAT=y/CONFIG_EXTRA_COMPAT=n/" \ - .config - make -C "$builddir" O="$PWD" silentoldconfig - make - - # build static - cd "$_staticdir" - msg "Building static busybox" - # enable internal ssl_client for static build - sed -e "s/.*CONFIG_PIE.*/\# CONFIG_PIE is not set/" \ - -e "s/.*CONFIG_STATIC.*/CONFIG_STATIC=y/" \ - -e "s/.*CONFIG_SSL_CLIENT.*/CONFIG_SSL_CLIENT=y/" \ - "$_config" > .config - # musl does not support GNU regex - [ "$CLIBC" = musl ] && sed -i \ - -e "s/CONFIG_EXTRA_COMPAT=y/CONFIG_EXTRA_COMPAT=n/" \ - .config - make -C "$builddir" O="$PWD" silentoldconfig - make - mv busybox busybox.static -} - -check() { - cd "$_dyndir" - SKIP_KNOWN_BUGS=1 make -C "$builddir" O="$PWD" V=1 check - - cd "$_dyndir_extras" - SKIP_KNOWN_BUGS=1 make -C "$builddir" O="$PWD" V=1 check -} - -package() { - cd "$_dyndir" - mkdir -p "$pkgdir"/usr/sbin "$pkgdir"/usr/bin "$pkgdir"/tmp \ - "$pkgdir"/var/cache/misc "$pkgdir"/bin "$pkgdir"/sbin - chmod 1777 "$pkgdir"/tmp - install -m755 busybox "$pkgdir"/bin/busybox || return 1 - # we need /bin/sh to be able to execute post-install - ln -s /bin/busybox "$pkgdir"/bin/sh - - #ifupdown needs those dirs to be present - mkdir -p \ - "$pkgdir"/etc/network/if-down.d \ - "$pkgdir"/etc/network/if-post-down.d \ - "$pkgdir"/etc/network/if-post-up.d \ - "$pkgdir"/etc/network/if-pre-down.d \ - "$pkgdir"/etc/network/if-pre-up.d \ - "$pkgdir"/etc/network/if-up.d - install -m775 "$srcdir"/dad.if-up "$pkgdir"/etc/network/if-up.d/dad - - install -Dm644 "$srcdir"/acpid.logrotate \ - "$pkgdir/etc/logrotate.d/acpid" - - mkdir -p "$pkgdir"/var/lib/udhcpd - install -Dm644 "$builddir"/examples/udhcp/udhcpd.conf \ - "$pkgdir"/etc/udhcpd.conf - cat >"$pkgdir"/etc/securetty <<EOF -console -tty1 -tty2 -tty3 -tty4 -tty5 -tty6 -tty7 -tty8 -tty9 -tty10 -tty11 -EOF -} - -extras() { - pkgdesc="Additional binaries of Busybox" - depends="${pkgname}" - install -Dm755 "$_dyndir_extras"/busybox "$subpkgdir"/bin/busybox-extras -} - -suid() { - pkgdesc="suid binaries of Busybox" - depends="${pkgname}" - - cd "$_dyndir" - mkdir -p "$subpkgdir"/bin - install -m4111 bbsuid "$subpkgdir"/bin/bbsuid -} - -static() { - pkgdesc="Statically linked Busybox" - mkdir -p "$subpkgdir"/bin - install -m755 "$_staticdir"/busybox.static \ - "$subpkgdir"/bin/busybox.static -} - -binsh() { - pkgdesc="Provide /bin/sh with BusyBox ash" - depends="${pkgname}" - provides="/bin/sh" - provider_priority=0 - - mkdir -p "$subpkgdir"/bin - mv "$pkgdir"/bin/sh "$subpkgdir"/bin -} - -sha512sums="92471617fcf3c1e28b468f3de2c83a1041f5ba5106580cc791e9c4cd602b7ccffabc51ce0807881ed734a89c3089113048265d6659a4d595528bd9150288d2ed busybox-1.28.4.tar.bz2 -51d4d58baff825a51d476bd4594cb8980ec2aa4d0c864a0eec39ccbbadd1ae9f1cd1b20f492a735ffcdf7c925573594f3c4363b0561c8aa7b91ef534bfc7b2e0 0001-ash-add-support-for-command_not_found_handle-hook-fu.patch -5d2fd3e521ee29d970f377363e3a3144eaf9f7714bc57494d743ded9e39c1ad93ea8759b2febd9c3786968b41e61b8d01ce2361aa997df177b644d63718470ba 0002-fsck-resolve-LABEL-.-UUID-.-spec-to-device.patch -cc5e5ce7a822ef51eb6b8065e1b802bc9d690857b8123cb4decf51b09c4ef655784401a68dd26e0a681fbb64bd2c0fed4001be6e33cac9049e516587ea53c17d 0003-ash-exec-busybox.static.patch -5f0611d21d1dc106d43ba23234babd41a2167d7032f3b09e825ae3dc9f9aaeb8d1882f59341daff99adecdfb8ba52a5c9fb423c8df3168b2e2304c5bd0ac4991 0004-app-location-for-cpio-vi-and-lspci.patch -bd4bb1f29f0287aa2ae4e43d791072802ba4f8863ea968612410a2819f7afaec5c0c731b4d91f360461ebfe26942f21e9ff69cbd5fb7d9800e62ef59fe954ab2 0005-udhcpc-set-default-discover-retries-to-5.patch -f03f852b97f3875d3051b225e6ffe52ed02ae8a8550287b3e09c2ef4d63914e1ab045ba5e2bc2dc2f3c8bf643485de4ebb36b97c74a8a6e49b6ba0261f2ddb94 0006-ping-make-ping-work-without-root-privileges.patch -a7b4ddb838f51e86040246e11a4b0df7bce37ed5159634bd2a8f388cf57be0551e6e63887b71b530a8a7b86dbdda6bbb3a090173f040050ea864b5f07674395d 0007-fbsplash-support-console-switching.patch -f8655833f71715629a4a93997939ca295cacb35f17843a36cb6fda285213bdbd258b2f84e321f81859491971412a520f697748ebd6fb46808f830f4ccfa77af4 0008-fbsplash-support-image-and-bar-alignment-and-positio.patch -f69031d048aa5e087cb6597ad2f7b39b520a5ef3713731e9090c5b65680cd7075bdf3a9443725fac49dce4345bc3345dc702b95d618d45a6d3be8682844784f4 0009-depmod-support-generating-kmod-binary-index-files.patch -b558f3ceb63e39545c3219796da64a7962bb53515a4eedea2bf9d81057774096b429145f0cd98da2542e3bdadaf92fb11d710fb1879768c9980bf58ccd104b6e 0010-Add-flag-for-not-following-symlinks-when-recursing.patch -f81d7966133d40a5d79cab4a4edf695bf7cc1f06cf2382c4ed99eea3a72cd222fe36c7b92e427262f67a81fcc2e7f6bff5986b32362c38da3c5163a49fd1ecab 0011-sysklogd-add-Z-option-to-adjust-message-timezones.patch -a96aa81d2f0104b5c28f02e80b3f77dbce77af93c174c09015a34850474d69e42c160fc8061c62f03465b6f793ead109dde7b0cc367d1e87694805d823f19d7e 0012-udhcpc-Don-t-background-if-n-is-given.patch -40c125a2ba19bcfaec46084bef98acb775a7f2521d854df41411afcfbc3025a1bdd029b0baf74550923db2541c23c1e9df5d5ded799d1d46dd7cf86a495e4c57 0013-testsuite-fix-cpio-tests.patch -4cbd38a3c2730ae38e34c5973bb63e40609c32f700d4943cc0e922394e8ee522d1512eb19c7885f5cee49834ab22b2594cb07164cacffefa39964a3b863f4e50 0014-miscutils-microcom-Fixed-segfault.patch -832eb44c52d2caad4bf6ea79fb17f10c116de3e90ed79038dabe3736d8e74507d1e0cb6f4f7689b4dd506b92437d8df7862038fc0213ecda259e40baf9d9b3de 0015-ash-introduce-a-config-option-to-search-current-dire.patch -185f11578dc3c3637f1acd1285c71b9e31f4244c57cd85b0848912c085a7a8c833d4c935ab1cadcb9852cf3185c7ffb08db8ea728fb19ab6e6fa90d89f13c75b 0016-top-handle-much-larger-VSZ-values.patch -d90d6b3406760fe3df6dbed46a0f4d1c02a69d5184ebc86d8c1692bc4576532127283ba3ff9a81e64f3660c279b8ee324dac7a426350873c45957067648651c6 0017-ifupdown-do-not-fail-if-interface-disappears-during-.patch -0dbe3ee424c0a6e4aba4f551f6b6b9ee087655a03747a40906961b141d40b1cbb2345438f17887a1b78d880cb3a7ad0116936dd7c05e95160febfd299423e83b 0001-cat-fix-cat-e-and-cat-v-erroneously-numbering-1st-li.patch -90f9e95f6f953df2cf579f701b3135bad910f514e94b3e23b953acec12b10f33aa9200169dc7b454c6a04fbd992a370e6ca835406f9b5495951e0a8416137000 0001-wget-emit-a-message-that-certificate-verification-is.patch -a9b1403c844c51934637215307dd9e2adb9458921047acff0d86dcf229b6e0027f4b2c6cdaa25a58407aad9d098fb5685d58eb5ff8d2aa3de4912cdea21fe54c acpid.logrotate -d65dc165488a179ab19482ad74e350df9dfdccf2363b26424d2d145e27ab0819cd0cfdfb79b4a2bd0bd7c6eda3b95ea61f3c264357986e78c4675df94d487aec busyboxconfig -0efbe22e2fd56993d92b6542d4ccffb2b42d50495be085c98f417a71f503b4071e2f092afcec77f78064d33ffb0922c28daa3cb9958e6d7fb26d5a660abd90f4 busyboxconfig-extras -0becc2186d6c32fb0c401cf7bc0e46268b38ce8892db33be1daf40273024c1c02d518283f44086a313a2ccef34230a1d945ec148cc173f26e6aa9d88a7426e54 bbsuid.c -a1127c8a384294135e11500fde7ead33b73d24b11c21911b08447a4c4ef71d7a9965d6466f60f2da64e3b877213b0a3e924a5add3c5333ee3ecde8c2a91c5e02 dad.if-up -061f7417c1cbf0424a5fab77e2f5912aa1593f39b33ea294af4c03518ca712d793a77ea82ff1f36e9cb98751d9faacb9d0240cdf0894efd8f26c13c28a692404 nologin.c" diff --git a/legacy/busybox/acpid.logrotate b/legacy/busybox/acpid.logrotate deleted file mode 100644 index a37763540..000000000 --- a/legacy/busybox/acpid.logrotate +++ /dev/null @@ -1,8 +0,0 @@ -/var/log/acpid.log { - missingok - notifempty - sharedscripts - postrotate - /etc/init.d/acpid --ifstarted restart || true - endscript -} diff --git a/legacy/busybox/bbsuid.c b/legacy/busybox/bbsuid.c deleted file mode 100644 index 24d0d7d3e..000000000 --- a/legacy/busybox/bbsuid.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2008 Natanael Copa <natanael.copa@gmail.com> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. See http://www.gnu.org/ for details. - * - */ - -#include <sys/stat.h> -#include <sys/types.h> - -#include <libgen.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <err.h> - -#define BBSUID_PATH "/bin/bbsuid" - -const static char * applets[] = { - "/bin/mount", - "/bin/umount", - "/bin/su", - "/usr/bin/crontab", - "/usr/bin/passwd", - "/usr/bin/traceroute", - "/usr/bin/traceroute6", - "/usr/bin/vlock", - NULL -}; - - -static const char *applet_from_path(const char *str) -{ - const char *p = strrchr(str, '/'); - if (p == NULL) - p = str; - else - p++; - return p; -} - -static int is_valid_applet(const char *str) -{ - int i; - for (i = 0; applets[i] != NULL; i++) { - const char *a = applet_from_path(applets[i]); - if (strcmp(applet_from_path(str), a) == 0) - return 1; - } - return 0; -} - -int exec_busybox(const char *app, int argc, char **argv) -{ - char **newargv = malloc((argc + 2) * sizeof(char *)); - int i; - newargv[0] = "/bin/busybox"; - newargv[1] = (char *)app; - for (i = 1; i < argc; i++) - newargv[i+1] = argv[i]; - newargv[argc+1] = NULL; - execv(newargv[0], newargv); - perror(newargv[0]); - free(newargv); - return 1; -} - -static int install_links(void) -{ - int i, r = 0; - /* we don't want others than root to install the symlinks */ - if (getuid() != 0) - errx(1, "Only root can install symlinks"); - - for (i = 0; applets[i] != NULL; i++) { - const char *a = applets[i]; - struct stat st; - if (lstat(a, &st) == 0 && S_ISLNK(st.st_mode)) - unlink(a); - if (symlink(BBSUID_PATH, a) < 0) - r++; - } - - return r; -} - -int main(int argc, char **argv) -{ - const char *app = applet_from_path(argv[0]); - - if (strcmp(app, "bbsuid") == 0) { - if (argc == 2 && strcmp(argv[1], "--install") == 0) - return install_links(); - errx(1, "Use --install to install symlinks"); - } - - if (is_valid_applet(app)) - return exec_busybox(app, argc, argv); - - errx(1, "%s is not a valid applet", app); - return 1; -} - diff --git a/legacy/busybox/busybox-extras.post-install b/legacy/busybox/busybox-extras.post-install deleted file mode 100644 index a0327a691..000000000 --- a/legacy/busybox/busybox-extras.post-install +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# Create all symlinks -exec /bin/busybox-extras --install -s diff --git a/legacy/busybox/busybox-extras.pre-deinstall b/legacy/busybox/busybox-extras.pre-deinstall deleted file mode 100644 index 15461302c..000000000 --- a/legacy/busybox/busybox-extras.pre-deinstall +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -# Remove all symlinks to busybox-extras -cd / -for link in $(busybox-extras --list --full); do - if [ -L "$link" ] && [ "$(readlink $link)" = "/bin/busybox-extras" ]; then - rm "$link" - fi -done diff --git a/legacy/busybox/busybox.post-install b/legacy/busybox/busybox.post-install deleted file mode 100644 index a986b2f76..000000000 --- a/legacy/busybox/busybox.post-install +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# We need the symlinks early -exec /bin/busybox --install -s diff --git a/legacy/busybox/busybox.post-upgrade b/legacy/busybox/busybox.post-upgrade deleted file mode 100644 index 291ed7a6d..000000000 --- a/legacy/busybox/busybox.post-upgrade +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -# remove links that has been relocated -for link in /bin/install /bin/ip /bin/vi /usr/bin/lspci; do - if [ -L "$link" ] && [ "$(readlink $link)" = "/bin/busybox" ]; then - rm "$link" - fi -done -for link in /bin/ping /bin/ping6; do - if [ -L "$link" ] && [ "$(readlink $link)" = "/bin/bbsuid" ]; then - rm "$link" - fi -done - -# remove links of programs moved to busybox-extras -for link in /usr/bin/telnet /usr/sbin/httpd /usr/bin/ftpget /usr/bin/ftpput \ - /usr/sbin/ftpd /usr/bin/tftp /usr/sbin/fakeidentd /usr/sbin/dnsd \ - /usr/sbin/inetd /usr/sbin/udhcpd; do - if [ -L "$link" ] && [ "$(readlink $link)" = "/bin/busybox" ]; then - rm "$link" - echo "NOTE: $link has been moved to the package 'busybox-extras'" - fi -done - -# We need the symlinks early -exec /bin/busybox --install -s diff --git a/legacy/busybox/busybox.pre-deinstall b/legacy/busybox/busybox.pre-deinstall deleted file mode 100644 index f1e10ba92..000000000 --- a/legacy/busybox/busybox.pre-deinstall +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -# Remove all symlinks to busybox -cd / -for link in $(busybox --list-full); do - if [ -L "$link" ] && [ "$(readlink $link)" = "/bin/busybox" ]; then - rm "$link" - fi -done diff --git a/legacy/busybox/busybox.trigger b/legacy/busybox/busybox.trigger deleted file mode 100644 index e531a45b8..000000000 --- a/legacy/busybox/busybox.trigger +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -do_bb_install= - -for i in "$@"; do - case "$i" in - /lib/modules/*) - if [ -d "$i" ]; then - /bin/busybox depmod ${i#/lib/modules/} - fi - ;; - *) do_bb_install=yes;; - esac -done - -if [ -n "$do_bb_install" ]; then - [ -e /bin/bbsuid ] && /bin/bbsuid --install - [ -e /bin/busybox-extras ] && /bin/busybox-extras --install -s - /bin/busybox --install -s -fi diff --git a/legacy/busybox/busyboxconfig b/legacy/busybox/busyboxconfig deleted file mode 100644 index d2ea6fd75..000000000 --- a/legacy/busybox/busyboxconfig +++ /dev/null @@ -1,1155 +0,0 @@ -# -# Automatically generated make config: don't edit -# Busybox version: 1.28.2 -# Wed Mar 28 12:24:02 2018 -# -CONFIG_HAVE_DOT_CONFIG=y - -# -# Settings -# -CONFIG_DESKTOP=y -# CONFIG_EXTRA_COMPAT is not set -# CONFIG_FEDORA_COMPAT is not set -# CONFIG_INCLUDE_SUSv2 is not set -CONFIG_LONG_OPTS=y -CONFIG_SHOW_USAGE=y -CONFIG_FEATURE_VERBOSE_USAGE=y -CONFIG_FEATURE_COMPRESS_USAGE=y -CONFIG_LFS=y -# CONFIG_PAM is not set -CONFIG_FEATURE_DEVPTS=y -# CONFIG_FEATURE_UTMP is not set -# CONFIG_FEATURE_WTMP is not set -CONFIG_FEATURE_PIDFILE=y -CONFIG_PID_FILE_PATH="/var/run" -CONFIG_BUSYBOX=y -CONFIG_FEATURE_INSTALLER=y -# CONFIG_INSTALL_NO_USR is not set -CONFIG_FEATURE_SUID=y -# CONFIG_FEATURE_SUID_CONFIG is not set -# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set -# CONFIG_FEATURE_PREFER_APPLETS is not set -CONFIG_BUSYBOX_EXEC_PATH="/bin/busybox" -# CONFIG_SELINUX is not set -# CONFIG_FEATURE_CLEAN_UP is not set -CONFIG_FEATURE_SYSLOG=y -CONFIG_PLATFORM_LINUX=y - -# -# Build Options -# -# CONFIG_STATIC is not set -CONFIG_PIE=y -# CONFIG_NOMMU is not set -# CONFIG_BUILD_LIBBUSYBOX is not set -# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set -# CONFIG_FEATURE_INDIVIDUAL is not set -# CONFIG_FEATURE_SHARED_BUSYBOX is not set -CONFIG_CROSS_COMPILER_PREFIX="" -CONFIG_SYSROOT="" -CONFIG_EXTRA_CFLAGS="" -CONFIG_EXTRA_LDFLAGS="" -CONFIG_EXTRA_LDLIBS="" -# CONFIG_USE_PORTABLE_CODE is not set - -# -# Installation Options ("make install" behavior) -# -# CONFIG_INSTALL_APPLET_SYMLINKS is not set -# CONFIG_INSTALL_APPLET_HARDLINKS is not set -# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set -CONFIG_INSTALL_APPLET_DONT=y -# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set -# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set -# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set -CONFIG_PREFIX="/home/ncopa/aports/main/busybox/pkg/busybox" - -# -# Debugging Options -# -# CONFIG_DEBUG is not set -# CONFIG_DEBUG_PESSIMIZE is not set -# CONFIG_DEBUG_SANITIZE is not set -# CONFIG_UNIT_TEST is not set -# CONFIG_WERROR is not set -CONFIG_NO_DEBUG_LIB=y -# CONFIG_DMALLOC is not set -# CONFIG_EFENCE is not set - -# -# Library Tuning -# -# CONFIG_FEATURE_USE_BSS_TAIL is not set -CONFIG_FEATURE_RTMINMAX=y -CONFIG_FEATURE_BUFFERS_USE_MALLOC=y -# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set -# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set -CONFIG_PASSWORD_MINLEN=6 -CONFIG_MD5_SMALL=0 -CONFIG_SHA3_SMALL=0 -CONFIG_FEATURE_FAST_TOP=y -# CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_EDITING=y -CONFIG_FEATURE_EDITING_MAX_LEN=1024 -CONFIG_FEATURE_EDITING_VI=y -CONFIG_FEATURE_EDITING_HISTORY=8192 -CONFIG_FEATURE_EDITING_SAVEHISTORY=y -# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set -CONFIG_FEATURE_REVERSE_SEARCH=y -CONFIG_FEATURE_TAB_COMPLETION=y -CONFIG_FEATURE_USERNAME_COMPLETION=y -CONFIG_FEATURE_EDITING_FANCY_PROMPT=y -CONFIG_FEATURE_EDITING_ASK_TERMINAL=y -CONFIG_LOCALE_SUPPORT=y -CONFIG_UNICODE_SUPPORT=y -CONFIG_UNICODE_USING_LOCALE=y -# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set -CONFIG_SUBST_WCHAR=63 -CONFIG_LAST_SUPPORTED_WCHAR=1114111 -CONFIG_UNICODE_COMBINING_WCHARS=y -CONFIG_UNICODE_WIDE_WCHARS=y -# CONFIG_UNICODE_BIDI_SUPPORT is not set -# CONFIG_UNICODE_NEUTRAL_TABLE is not set -CONFIG_UNICODE_PRESERVE_BROKEN=y -CONFIG_FEATURE_NON_POSIX_CP=y -# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set -CONFIG_FEATURE_USE_SENDFILE=y -CONFIG_FEATURE_COPYBUF_KB=16 -CONFIG_FEATURE_SKIP_ROOTFS=y -CONFIG_MONOTONIC_SYSCALL=y -# CONFIG_IOCTL_HEX2STR_ERROR is not set -CONFIG_FEATURE_HWIB=y - -# -# Applets -# - -# -# Archival Utilities -# -CONFIG_FEATURE_SEAMLESS_XZ=y -CONFIG_FEATURE_SEAMLESS_LZMA=y -CONFIG_FEATURE_SEAMLESS_BZ2=y -CONFIG_FEATURE_SEAMLESS_GZ=y -CONFIG_FEATURE_SEAMLESS_Z=y -# CONFIG_AR is not set -# CONFIG_FEATURE_AR_LONG_FILENAMES is not set -# CONFIG_FEATURE_AR_CREATE is not set -# CONFIG_UNCOMPRESS is not set -CONFIG_GUNZIP=y -CONFIG_ZCAT=y -CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y -CONFIG_BUNZIP2=y -CONFIG_BZCAT=y -CONFIG_UNLZMA=y -CONFIG_LZCAT=y -CONFIG_LZMA=y -CONFIG_UNXZ=y -CONFIG_XZCAT=y -# CONFIG_XZ is not set -CONFIG_BZIP2=y -CONFIG_FEATURE_BZIP2_DECOMPRESS=y -CONFIG_CPIO=y -CONFIG_FEATURE_CPIO_O=y -CONFIG_FEATURE_CPIO_P=y -# CONFIG_DPKG is not set -# CONFIG_DPKG_DEB is not set -CONFIG_GZIP=y -# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set -CONFIG_GZIP_FAST=2 -CONFIG_FEATURE_GZIP_LEVELS=y -CONFIG_FEATURE_GZIP_DECOMPRESS=y -CONFIG_LZOP=y -CONFIG_UNLZOP=y -CONFIG_LZOPCAT=y -# CONFIG_LZOP_COMPR_HIGH is not set -# CONFIG_RPM is not set -# CONFIG_RPM2CPIO is not set -CONFIG_TAR=y -CONFIG_FEATURE_TAR_LONG_OPTIONS=y -CONFIG_FEATURE_TAR_CREATE=y -CONFIG_FEATURE_TAR_AUTODETECT=y -CONFIG_FEATURE_TAR_FROM=y -CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y -CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y -CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y -# CONFIG_FEATURE_TAR_TO_COMMAND is not set -CONFIG_FEATURE_TAR_UNAME_GNAME=y -CONFIG_FEATURE_TAR_NOPRESERVE_TIME=y -# CONFIG_FEATURE_TAR_SELINUX is not set -CONFIG_UNZIP=y -CONFIG_FEATURE_UNZIP_CDF=y -CONFIG_FEATURE_UNZIP_BZIP2=y -CONFIG_FEATURE_UNZIP_LZMA=y -CONFIG_FEATURE_UNZIP_XZ=y -CONFIG_FEATURE_LZMA_FAST=y - -# -# Coreutils -# -CONFIG_BASENAME=y -CONFIG_CAT=y -CONFIG_FEATURE_CATN=y -CONFIG_FEATURE_CATV=y -CONFIG_CHGRP=y -CONFIG_CHMOD=y -CONFIG_CHOWN=y -CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y -CONFIG_CHROOT=y -CONFIG_CKSUM=y -CONFIG_COMM=y -CONFIG_CP=y -CONFIG_FEATURE_CP_LONG_OPTIONS=y -CONFIG_CUT=y -CONFIG_DATE=y -CONFIG_FEATURE_DATE_ISOFMT=y -# CONFIG_FEATURE_DATE_NANO is not set -CONFIG_FEATURE_DATE_COMPAT=y -CONFIG_DD=y -CONFIG_FEATURE_DD_SIGNAL_HANDLING=y -# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set -CONFIG_FEATURE_DD_IBS_OBS=y -CONFIG_FEATURE_DD_STATUS=y -CONFIG_DF=y -CONFIG_FEATURE_DF_FANCY=y -CONFIG_DIRNAME=y -CONFIG_DOS2UNIX=y -CONFIG_UNIX2DOS=y -CONFIG_DU=y -CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y -CONFIG_ECHO=y -CONFIG_FEATURE_FANCY_ECHO=y -CONFIG_ENV=y -CONFIG_EXPAND=y -CONFIG_UNEXPAND=y -CONFIG_EXPR=y -CONFIG_EXPR_MATH_SUPPORT_64=y -CONFIG_FACTOR=y -CONFIG_FALSE=y -CONFIG_FOLD=y -CONFIG_FSYNC=y -CONFIG_HEAD=y -CONFIG_FEATURE_FANCY_HEAD=y -CONFIG_HOSTID=y -CONFIG_ID=y -CONFIG_GROUPS=y -CONFIG_INSTALL=y -# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set -CONFIG_LINK=y -CONFIG_LN=y -# CONFIG_LOGNAME is not set -CONFIG_LS=y -CONFIG_FEATURE_LS_FILETYPES=y -CONFIG_FEATURE_LS_FOLLOWLINKS=y -CONFIG_FEATURE_LS_RECURSIVE=y -CONFIG_FEATURE_LS_WIDTH=y -CONFIG_FEATURE_LS_SORTFILES=y -CONFIG_FEATURE_LS_TIMESTAMPS=y -CONFIG_FEATURE_LS_USERNAME=y -CONFIG_FEATURE_LS_COLOR=y -CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y -CONFIG_MD5SUM=y -CONFIG_SHA1SUM=y -CONFIG_SHA256SUM=y -CONFIG_SHA512SUM=y -CONFIG_SHA3SUM=y - -# -# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum -# -CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y -CONFIG_MKDIR=y -CONFIG_MKFIFO=y -CONFIG_MKNOD=y -CONFIG_MKTEMP=y -CONFIG_MV=y -CONFIG_NICE=y -CONFIG_NL=y -CONFIG_NOHUP=y -CONFIG_NPROC=y -CONFIG_OD=y -CONFIG_PASTE=y -CONFIG_PRINTENV=y -CONFIG_PRINTF=y -CONFIG_PWD=y -CONFIG_READLINK=y -CONFIG_FEATURE_READLINK_FOLLOW=y -CONFIG_REALPATH=y -CONFIG_RM=y -CONFIG_RMDIR=y -CONFIG_SEQ=y -CONFIG_SHRED=y -CONFIG_SHUF=y -CONFIG_SLEEP=y -CONFIG_FEATURE_FANCY_SLEEP=y -CONFIG_FEATURE_FLOAT_SLEEP=y -CONFIG_SORT=y -CONFIG_FEATURE_SORT_BIG=y -CONFIG_SPLIT=y -# CONFIG_FEATURE_SPLIT_FANCY is not set -CONFIG_STAT=y -CONFIG_FEATURE_STAT_FORMAT=y -CONFIG_FEATURE_STAT_FILESYSTEM=y -CONFIG_STTY=y -CONFIG_SUM=y -CONFIG_SYNC=y -CONFIG_FEATURE_SYNC_FANCY=y -CONFIG_TAC=y -CONFIG_TAIL=y -CONFIG_FEATURE_FANCY_TAIL=y -CONFIG_TEE=y -CONFIG_FEATURE_TEE_USE_BLOCK_IO=y -CONFIG_TEST=y -CONFIG_TEST1=y -CONFIG_TEST2=y -CONFIG_FEATURE_TEST_64=y -CONFIG_TIMEOUT=y -CONFIG_TOUCH=y -CONFIG_FEATURE_TOUCH_NODEREF=y -CONFIG_FEATURE_TOUCH_SUSV3=y -CONFIG_TR=y -CONFIG_FEATURE_TR_CLASSES=y -CONFIG_FEATURE_TR_EQUIV=y -CONFIG_TRUE=y -CONFIG_TRUNCATE=y -CONFIG_TTY=y -CONFIG_UNAME=y -CONFIG_UNAME_OSNAME="Linux" -CONFIG_BB_ARCH=y -CONFIG_UNIQ=y -CONFIG_UNLINK=y -CONFIG_USLEEP=y -CONFIG_UUDECODE=y -CONFIG_BASE64=y -CONFIG_UUENCODE=y -CONFIG_WC=y -# CONFIG_FEATURE_WC_LARGE is not set -# CONFIG_WHO is not set -# CONFIG_W is not set -# CONFIG_USERS is not set -CONFIG_WHOAMI=y -CONFIG_YES=y - -# -# Common options -# -CONFIG_FEATURE_VERBOSE=y - -# -# Common options for cp and mv -# -CONFIG_FEATURE_PRESERVE_HARDLINKS=y - -# -# Common options for df, du, ls -# -CONFIG_FEATURE_HUMAN_READABLE=y - -# -# Console Utilities -# -CONFIG_CHVT=y -CONFIG_CLEAR=y -CONFIG_DEALLOCVT=y -CONFIG_DUMPKMAP=y -# CONFIG_FGCONSOLE is not set -CONFIG_KBD_MODE=y -CONFIG_LOADFONT=y -CONFIG_SETFONT=y -CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y -CONFIG_DEFAULT_SETFONT_DIR="/usr/share" - -# -# Common options for loadfont and setfont -# -CONFIG_FEATURE_LOADFONT_PSF2=y -CONFIG_FEATURE_LOADFONT_RAW=y -CONFIG_LOADKMAP=y -CONFIG_OPENVT=y -CONFIG_RESET=y -CONFIG_RESIZE=y -CONFIG_FEATURE_RESIZE_PRINT=y -CONFIG_SETCONSOLE=y -# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set -CONFIG_SETKEYCODES=y -CONFIG_SETLOGCONS=y -CONFIG_SHOWKEY=y - -# -# Debian Utilities -# -CONFIG_PIPE_PROGRESS=y -CONFIG_RUN_PARTS=y -CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y -# CONFIG_FEATURE_RUN_PARTS_FANCY is not set -# CONFIG_START_STOP_DAEMON is not set -# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set -# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set -CONFIG_WHICH=y - -# -# klibc-utils -# -# CONFIG_MINIPS is not set -# CONFIG_NUKE is not set -# CONFIG_RESUME is not set -# CONFIG_RUN_INIT is not set - -# -# Editors -# -CONFIG_AWK=y -CONFIG_FEATURE_AWK_LIBM=y -CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y -CONFIG_CMP=y -CONFIG_DIFF=y -CONFIG_FEATURE_DIFF_LONG_OPTIONS=y -CONFIG_FEATURE_DIFF_DIR=y -CONFIG_ED=y -CONFIG_PATCH=y -CONFIG_SED=y -CONFIG_VI=y -CONFIG_FEATURE_VI_MAX_LEN=1024 -CONFIG_FEATURE_VI_8BIT=y -CONFIG_FEATURE_VI_COLON=y -CONFIG_FEATURE_VI_YANKMARK=y -CONFIG_FEATURE_VI_SEARCH=y -# CONFIG_FEATURE_VI_REGEX_SEARCH is not set -CONFIG_FEATURE_VI_USE_SIGNALS=y -CONFIG_FEATURE_VI_DOT_CMD=y -CONFIG_FEATURE_VI_READONLY=y -CONFIG_FEATURE_VI_SETOPTS=y -CONFIG_FEATURE_VI_SET=y -CONFIG_FEATURE_VI_WIN_RESIZE=y -CONFIG_FEATURE_VI_ASK_TERMINAL=y -CONFIG_FEATURE_VI_UNDO=y -CONFIG_FEATURE_VI_UNDO_QUEUE=y -CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256 -CONFIG_FEATURE_ALLOW_EXEC=y - -# -# Finding Utilities -# -CONFIG_FIND=y -CONFIG_FEATURE_FIND_PRINT0=y -CONFIG_FEATURE_FIND_MTIME=y -CONFIG_FEATURE_FIND_MMIN=y -CONFIG_FEATURE_FIND_PERM=y -CONFIG_FEATURE_FIND_TYPE=y -CONFIG_FEATURE_FIND_XDEV=y -CONFIG_FEATURE_FIND_MAXDEPTH=y -CONFIG_FEATURE_FIND_NEWER=y -CONFIG_FEATURE_FIND_INUM=y -CONFIG_FEATURE_FIND_EXEC=y -CONFIG_FEATURE_FIND_EXEC_PLUS=y -CONFIG_FEATURE_FIND_USER=y -CONFIG_FEATURE_FIND_GROUP=y -CONFIG_FEATURE_FIND_NOT=y -CONFIG_FEATURE_FIND_DEPTH=y -CONFIG_FEATURE_FIND_PAREN=y -CONFIG_FEATURE_FIND_SIZE=y -CONFIG_FEATURE_FIND_PRUNE=y -CONFIG_FEATURE_FIND_DELETE=y -CONFIG_FEATURE_FIND_PATH=y -CONFIG_FEATURE_FIND_REGEX=y -# CONFIG_FEATURE_FIND_CONTEXT is not set -CONFIG_FEATURE_FIND_LINKS=y -CONFIG_GREP=y -CONFIG_EGREP=y -CONFIG_FGREP=y -CONFIG_FEATURE_GREP_CONTEXT=y -CONFIG_XARGS=y -CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y -CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y -CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y -CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y -CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y -CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL=y -CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE=y - -# -# Init Utilities -# -# CONFIG_BOOTCHARTD is not set -# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set -# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set -CONFIG_HALT=y -CONFIG_POWEROFF=y -CONFIG_REBOOT=y -# CONFIG_FEATURE_CALL_TELINIT is not set -CONFIG_TELINIT_PATH="" -CONFIG_INIT=y -# CONFIG_LINUXRC is not set -CONFIG_FEATURE_USE_INITTAB=y -CONFIG_FEATURE_KILL_REMOVED=y -CONFIG_FEATURE_KILL_DELAY=0 -CONFIG_FEATURE_INIT_SCTTY=y -CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_INIT_QUIET=y -# CONFIG_FEATURE_INIT_COREDUMPS is not set -CONFIG_INIT_TERMINAL_TYPE="linux" -# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set - -# -# Login/Password Management Utilities -# -CONFIG_FEATURE_SHADOWPASSWDS=y -# CONFIG_USE_BB_PWD_GRP is not set -# CONFIG_USE_BB_SHADOW is not set -# CONFIG_USE_BB_CRYPT is not set -# CONFIG_USE_BB_CRYPT_SHA is not set -CONFIG_ADD_SHELL=y -CONFIG_REMOVE_SHELL=y -CONFIG_ADDGROUP=y -CONFIG_FEATURE_ADDUSER_TO_GROUP=y -CONFIG_ADDUSER=y -CONFIG_FEATURE_CHECK_NAMES=y -CONFIG_LAST_ID=256000 -CONFIG_FIRST_SYSTEM_ID=100 -CONFIG_LAST_SYSTEM_ID=999 -CONFIG_CHPASSWD=y -CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="sha512" -CONFIG_CRYPTPW=y -CONFIG_MKPASSWD=y -CONFIG_DELUSER=y -CONFIG_DELGROUP=y -CONFIG_FEATURE_DEL_USER_FROM_GROUP=y -CONFIG_GETTY=y -CONFIG_LOGIN=y -CONFIG_LOGIN_SESSION_AS_CHILD=y -CONFIG_LOGIN_SCRIPTS=y -CONFIG_FEATURE_NOLOGIN=y -CONFIG_FEATURE_SECURETTY=y -CONFIG_NOLOGIN=y -CONFIG_PASSWD=y -CONFIG_FEATURE_PASSWD_WEAK_CHECK=y -CONFIG_SU=y -CONFIG_FEATURE_SU_SYSLOG=y -CONFIG_FEATURE_SU_CHECKS_SHELLS=y -CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY=y -# CONFIG_SULOGIN is not set -CONFIG_VLOCK=y - -# -# Linux Ext2 FS Progs -# -# CONFIG_CHATTR is not set -CONFIG_FSCK=y -# CONFIG_LSATTR is not set -# CONFIG_TUNE2FS is not set - -# -# Linux Module Utilities -# -# CONFIG_MODPROBE_SMALL is not set -CONFIG_DEPMOD=y -CONFIG_INSMOD=y -CONFIG_LSMOD=y -CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y -CONFIG_MODINFO=y -CONFIG_MODPROBE=y -CONFIG_FEATURE_MODPROBE_BLACKLIST=y -CONFIG_RMMOD=y - -# -# Options common to multiple modutils -# -CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS=y -# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set -# CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set -# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set -# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set -CONFIG_FEATURE_CHECK_TAINTED_MODULE=y -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set -CONFIG_FEATURE_MODUTILS_ALIAS=y -CONFIG_FEATURE_MODUTILS_BIN=y -CONFIG_FEATURE_MODUTILS_SYMBOLS=y -CONFIG_DEFAULT_MODULES_DIR="/lib/modules" -CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" - -# -# Linux System Utilities -# -CONFIG_ACPID=y -CONFIG_FEATURE_ACPID_COMPAT=y -CONFIG_BLKDISCARD=y -CONFIG_BLKID=y -CONFIG_FEATURE_BLKID_TYPE=y -CONFIG_BLOCKDEV=y -CONFIG_CAL=y -# CONFIG_CHRT is not set -CONFIG_DMESG=y -CONFIG_FEATURE_DMESG_PRETTY=y -CONFIG_EJECT=y -CONFIG_FEATURE_EJECT_SCSI=y -CONFIG_FALLOCATE=y -CONFIG_FATATTR=y -CONFIG_FBSET=y -CONFIG_FEATURE_FBSET_FANCY=y -CONFIG_FEATURE_FBSET_READMODE=y -CONFIG_FDFORMAT=y -CONFIG_FDISK=y -# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set -CONFIG_FEATURE_FDISK_WRITABLE=y -CONFIG_FEATURE_AIX_LABEL=y -CONFIG_FEATURE_SGI_LABEL=y -CONFIG_FEATURE_SUN_LABEL=y -CONFIG_FEATURE_OSF_LABEL=y -CONFIG_FEATURE_GPT_LABEL=y -CONFIG_FEATURE_FDISK_ADVANCED=y -CONFIG_FINDFS=y -CONFIG_FLOCK=y -CONFIG_FDFLUSH=y -# CONFIG_FREERAMDISK is not set -# CONFIG_FSCK_MINIX is not set -# CONFIG_FSFREEZE is not set -CONFIG_FSTRIM=y -CONFIG_GETOPT=y -CONFIG_FEATURE_GETOPT_LONG=y -CONFIG_HEXDUMP=y -CONFIG_FEATURE_HEXDUMP_REVERSE=y -CONFIG_HD=y -CONFIG_XXD=y -CONFIG_HWCLOCK=y -CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y -CONFIG_IONICE=y -CONFIG_IPCRM=y -CONFIG_IPCS=y -# CONFIG_LAST is not set -# CONFIG_FEATURE_LAST_FANCY is not set -CONFIG_LOSETUP=y -CONFIG_LSPCI=y -CONFIG_LSUSB=y -CONFIG_MDEV=y -CONFIG_FEATURE_MDEV_CONF=y -CONFIG_FEATURE_MDEV_RENAME=y -CONFIG_FEATURE_MDEV_RENAME_REGEXP=y -CONFIG_FEATURE_MDEV_EXEC=y -CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y -CONFIG_MESG=y -CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y -# CONFIG_MKE2FS is not set -# CONFIG_MKFS_EXT2 is not set -# CONFIG_MKFS_MINIX is not set -# CONFIG_FEATURE_MINIX2 is not set -# CONFIG_MKFS_REISER is not set -CONFIG_MKDOSFS=y -CONFIG_MKFS_VFAT=y -CONFIG_MKSWAP=y -CONFIG_FEATURE_MKSWAP_UUID=y -CONFIG_MORE=y -CONFIG_MOUNT=y -CONFIG_FEATURE_MOUNT_FAKE=y -CONFIG_FEATURE_MOUNT_VERBOSE=y -CONFIG_FEATURE_MOUNT_HELPERS=y -CONFIG_FEATURE_MOUNT_LABEL=y -# CONFIG_FEATURE_MOUNT_NFS is not set -CONFIG_FEATURE_MOUNT_CIFS=y -CONFIG_FEATURE_MOUNT_FLAGS=y -CONFIG_FEATURE_MOUNT_FSTAB=y -# CONFIG_FEATURE_MOUNT_OTHERTAB is not set -CONFIG_MOUNTPOINT=y -CONFIG_NSENTER=y -# CONFIG_PIVOT_ROOT is not set -CONFIG_RDATE=y -CONFIG_RDEV=y -CONFIG_READPROFILE=y -CONFIG_RENICE=y -CONFIG_REV=y -# CONFIG_RTCWAKE is not set -# CONFIG_SCRIPT is not set -# CONFIG_SCRIPTREPLAY is not set -# CONFIG_SETARCH is not set -CONFIG_LINUX32=y -CONFIG_LINUX64=y -CONFIG_SETPRIV=y -CONFIG_FEATURE_SETPRIV_DUMP=y -CONFIG_FEATURE_SETPRIV_CAPABILITIES=y -CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES=y -CONFIG_SETSID=y -CONFIG_SWAPON=y -CONFIG_FEATURE_SWAPON_DISCARD=y -CONFIG_FEATURE_SWAPON_PRI=y -CONFIG_SWAPOFF=y -CONFIG_FEATURE_SWAPONOFF_LABEL=y -CONFIG_SWITCH_ROOT=y -# CONFIG_TASKSET is not set -# CONFIG_FEATURE_TASKSET_FANCY is not set -# CONFIG_UEVENT is not set -CONFIG_UMOUNT=y -CONFIG_FEATURE_UMOUNT_ALL=y -CONFIG_UNSHARE=y -# CONFIG_WALL is not set - -# -# Common options for mount/umount -# -CONFIG_FEATURE_MOUNT_LOOP=y -CONFIG_FEATURE_MOUNT_LOOP_CREATE=y -# CONFIG_FEATURE_MTAB_SUPPORT is not set -CONFIG_VOLUMEID=y - -# -# Filesystem/Volume identification -# -CONFIG_FEATURE_VOLUMEID_BCACHE=y -CONFIG_FEATURE_VOLUMEID_BTRFS=y -CONFIG_FEATURE_VOLUMEID_CRAMFS=y -CONFIG_FEATURE_VOLUMEID_EXFAT=y -CONFIG_FEATURE_VOLUMEID_EXT=y -CONFIG_FEATURE_VOLUMEID_F2FS=y -CONFIG_FEATURE_VOLUMEID_FAT=y -# CONFIG_FEATURE_VOLUMEID_HFS is not set -CONFIG_FEATURE_VOLUMEID_ISO9660=y -CONFIG_FEATURE_VOLUMEID_JFS=y -CONFIG_FEATURE_VOLUMEID_LINUXRAID=y -CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y -CONFIG_FEATURE_VOLUMEID_LUKS=y -CONFIG_FEATURE_VOLUMEID_MINIX=y -CONFIG_FEATURE_VOLUMEID_NILFS=y -CONFIG_FEATURE_VOLUMEID_NTFS=y -CONFIG_FEATURE_VOLUMEID_OCFS2=y -CONFIG_FEATURE_VOLUMEID_REISERFS=y -# CONFIG_FEATURE_VOLUMEID_ROMFS is not set -CONFIG_FEATURE_VOLUMEID_SQUASHFS=y -# CONFIG_FEATURE_VOLUMEID_SYSV is not set -CONFIG_FEATURE_VOLUMEID_UBIFS=y -CONFIG_FEATURE_VOLUMEID_UDF=y -CONFIG_FEATURE_VOLUMEID_XFS=y - -# -# Miscellaneous Utilities -# -CONFIG_ADJTIMEX=y -CONFIG_BBCONFIG=y -CONFIG_FEATURE_COMPRESS_BBCONFIG=y -CONFIG_BEEP=y -CONFIG_FEATURE_BEEP_FREQ=440 -CONFIG_FEATURE_BEEP_LENGTH_MS=30 -# CONFIG_CHAT is not set -# CONFIG_FEATURE_CHAT_NOFAIL is not set -# CONFIG_FEATURE_CHAT_TTY_HIFI is not set -# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set -# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set -# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set -# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set -# CONFIG_FEATURE_CHAT_CLR_ABORT is not set -CONFIG_CONSPY=y -CONFIG_CROND=y -CONFIG_FEATURE_CROND_D=y -CONFIG_FEATURE_CROND_CALL_SENDMAIL=y -CONFIG_FEATURE_CROND_SPECIAL_TIMES=y -CONFIG_FEATURE_CROND_DIR="/var/spool/cron" -CONFIG_CRONTAB=y -CONFIG_DC=y -CONFIG_FEATURE_DC_LIBM=y -# CONFIG_DEVFSD is not set -# CONFIG_DEVFSD_MODLOAD is not set -# CONFIG_DEVFSD_FG_NP is not set -# CONFIG_DEVFSD_VERBOSE is not set -# CONFIG_FEATURE_DEVFS is not set -# CONFIG_DEVMEM is not set -CONFIG_FBSPLASH=y -# CONFIG_FLASH_ERASEALL is not set -# CONFIG_FLASH_LOCK is not set -# CONFIG_FLASH_UNLOCK is not set -# CONFIG_FLASHCP is not set -CONFIG_HDPARM=y -# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set -# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set -# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set -# CONFIG_HEXEDIT is not set -# CONFIG_I2CGET is not set -# CONFIG_I2CSET is not set -# CONFIG_I2CDUMP is not set -# CONFIG_I2CDETECT is not set -CONFIG_INOTIFYD=y -CONFIG_LESS=y -CONFIG_FEATURE_LESS_MAXLINES=9999999 -CONFIG_FEATURE_LESS_BRACKETS=y -CONFIG_FEATURE_LESS_FLAGS=y -CONFIG_FEATURE_LESS_TRUNCATE=y -CONFIG_FEATURE_LESS_MARKS=y -CONFIG_FEATURE_LESS_REGEXP=y -CONFIG_FEATURE_LESS_WINCH=y -CONFIG_FEATURE_LESS_ASK_TERMINAL=y -CONFIG_FEATURE_LESS_DASHCMD=y -CONFIG_FEATURE_LESS_LINENUMS=y -# CONFIG_LSSCSI is not set -# CONFIG_MAKEDEVS is not set -# CONFIG_FEATURE_MAKEDEVS_LEAF is not set -# CONFIG_FEATURE_MAKEDEVS_TABLE is not set -# CONFIG_MAN is not set -CONFIG_MICROCOM=y -# CONFIG_MT is not set -CONFIG_NANDWRITE=y -CONFIG_NANDDUMP=y -CONFIG_PARTPROBE=y -CONFIG_RAIDAUTORUN=y -CONFIG_READAHEAD=y -CONFIG_RFKILL=y -# CONFIG_RUNLEVEL is not set -# CONFIG_RX is not set -# CONFIG_SETFATTR is not set -CONFIG_SETSERIAL=y -CONFIG_STRINGS=y -CONFIG_TIME=y -CONFIG_TTYSIZE=y -# CONFIG_UBIATTACH is not set -# CONFIG_UBIDETACH is not set -# CONFIG_UBIMKVOL is not set -# CONFIG_UBIRMVOL is not set -# CONFIG_UBIRSVOL is not set -# CONFIG_UBIUPDATEVOL is not set -# CONFIG_UBIRENAME is not set -CONFIG_VOLNAME=y -CONFIG_WATCHDOG=y - -# -# Networking Utilities -# -CONFIG_FEATURE_IPV6=y -CONFIG_FEATURE_UNIX_LOCAL=y -CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y -CONFIG_VERBOSE_RESOLUTION_ERRORS=y -CONFIG_ARP=y -CONFIG_ARPING=y -CONFIG_BRCTL=y -CONFIG_FEATURE_BRCTL_FANCY=y -CONFIG_FEATURE_BRCTL_SHOW=y -# CONFIG_DNSD is not set -CONFIG_ETHER_WAKE=y -# CONFIG_FTPD is not set -# CONFIG_FEATURE_FTPD_WRITE is not set -# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set -# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set -# CONFIG_FTPGET is not set -# CONFIG_FTPPUT is not set -# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set -CONFIG_HOSTNAME=y -CONFIG_DNSDOMAINNAME=y -# CONFIG_HTTPD is not set -# CONFIG_FEATURE_HTTPD_RANGES is not set -# CONFIG_FEATURE_HTTPD_SETUID is not set -# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set -# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set -# CONFIG_FEATURE_HTTPD_CGI is not set -# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set -# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set -# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set -# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set -# CONFIG_FEATURE_HTTPD_PROXY is not set -# CONFIG_FEATURE_HTTPD_GZIP is not set -CONFIG_IFCONFIG=y -CONFIG_FEATURE_IFCONFIG_STATUS=y -CONFIG_FEATURE_IFCONFIG_SLIP=y -CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y -CONFIG_FEATURE_IFCONFIG_HW=y -CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y -CONFIG_IFENSLAVE=y -# CONFIG_IFPLUGD is not set -CONFIG_IFUP=y -CONFIG_IFDOWN=y -CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate" -CONFIG_FEATURE_IFUPDOWN_IP=y -CONFIG_FEATURE_IFUPDOWN_IPV4=y -CONFIG_FEATURE_IFUPDOWN_IPV6=y -# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set -CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP=y -# CONFIG_INETD is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set -# CONFIG_FEATURE_INETD_RPC is not set -CONFIG_IP=y -CONFIG_IPADDR=y -CONFIG_IPLINK=y -CONFIG_IPROUTE=y -CONFIG_IPTUNNEL=y -CONFIG_IPRULE=y -CONFIG_IPNEIGH=y -CONFIG_FEATURE_IP_ADDRESS=y -CONFIG_FEATURE_IP_LINK=y -CONFIG_FEATURE_IP_ROUTE=y -CONFIG_FEATURE_IP_ROUTE_DIR="/etc/iproute2" -CONFIG_FEATURE_IP_TUNNEL=y -CONFIG_FEATURE_IP_RULE=y -CONFIG_FEATURE_IP_NEIGH=y -CONFIG_FEATURE_IP_RARE_PROTOCOLS=y -CONFIG_IPCALC=y -# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set -CONFIG_FEATURE_IPCALC_FANCY=y -# CONFIG_FAKEIDENTD is not set -CONFIG_NAMEIF=y -CONFIG_FEATURE_NAMEIF_EXTENDED=y -CONFIG_NBDCLIENT=y -CONFIG_NC=y -# CONFIG_NETCAT is not set -CONFIG_NC_SERVER=y -CONFIG_NC_EXTRA=y -CONFIG_NC_110_COMPAT=y -CONFIG_NETSTAT=y -CONFIG_FEATURE_NETSTAT_WIDE=y -CONFIG_FEATURE_NETSTAT_PRG=y -CONFIG_NSLOOKUP=y -CONFIG_NTPD=y -CONFIG_FEATURE_NTPD_SERVER=y -CONFIG_FEATURE_NTPD_CONF=y -CONFIG_PING=y -CONFIG_PING6=y -CONFIG_FEATURE_FANCY_PING=y -CONFIG_PSCAN=y -CONFIG_ROUTE=y -CONFIG_SLATTACH=y -# CONFIG_SSL_CLIENT is not set -# CONFIG_TCPSVD is not set -# CONFIG_UDPSVD is not set -# CONFIG_TELNET is not set -# CONFIG_FEATURE_TELNET_TTYPE is not set -# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set -# CONFIG_FEATURE_TELNET_WIDTH is not set -# CONFIG_TELNETD is not set -# CONFIG_FEATURE_TELNETD_STANDALONE is not set -# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set -# CONFIG_TFTP is not set -# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set -# CONFIG_TFTPD is not set -# CONFIG_FEATURE_TFTP_GET is not set -# CONFIG_FEATURE_TFTP_PUT is not set -# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set -# CONFIG_TFTP_DEBUG is not set -# CONFIG_TLS is not set -CONFIG_TRACEROUTE=y -CONFIG_TRACEROUTE6=y -CONFIG_FEATURE_TRACEROUTE_VERBOSE=y -CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y -CONFIG_TUNCTL=y -CONFIG_FEATURE_TUNCTL_UG=y -CONFIG_VCONFIG=y -CONFIG_WGET=y -CONFIG_FEATURE_WGET_LONG_OPTIONS=y -CONFIG_FEATURE_WGET_STATUSBAR=y -CONFIG_FEATURE_WGET_AUTHENTICATION=y -CONFIG_FEATURE_WGET_TIMEOUT=y -CONFIG_FEATURE_WGET_HTTPS=y -# CONFIG_FEATURE_WGET_OPENSSL is not set -CONFIG_WHOIS=y -# CONFIG_ZCIP is not set -# CONFIG_UDHCPD is not set -# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set -# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set -CONFIG_DHCPD_LEASES_FILE="" -CONFIG_DUMPLEASES=y -# CONFIG_DHCPRELAY is not set -CONFIG_UDHCPC=y -CONFIG_FEATURE_UDHCPC_ARPING=y -CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y -CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" -CONFIG_UDHCPC6=y -CONFIG_FEATURE_UDHCPC6_RFC3646=y -CONFIG_FEATURE_UDHCPC6_RFC4704=y -CONFIG_FEATURE_UDHCPC6_RFC4833=y - -# -# Common options for DHCP applets -# -# CONFIG_FEATURE_UDHCP_PORT is not set -CONFIG_UDHCP_DEBUG=0 -CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 -CONFIG_FEATURE_UDHCP_RFC3397=y -CONFIG_FEATURE_UDHCP_8021Q=y -CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="-b" - -# -# Print Utilities -# -# CONFIG_LPD is not set -# CONFIG_LPR is not set -# CONFIG_LPQ is not set - -# -# Mail Utilities -# -CONFIG_MAKEMIME=y -# CONFIG_POPMAILDIR is not set -# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set -CONFIG_REFORMIME=y -CONFIG_FEATURE_REFORMIME_COMPAT=y -CONFIG_SENDMAIL=y -CONFIG_FEATURE_MIME_CHARSET="us-ascii" - -# -# Process Utilities -# -CONFIG_FREE=y -CONFIG_FUSER=y -CONFIG_IOSTAT=y -CONFIG_KILL=y -CONFIG_KILLALL=y -CONFIG_KILLALL5=y -CONFIG_LSOF=y -CONFIG_MPSTAT=y -CONFIG_NMETER=y -CONFIG_PGREP=y -CONFIG_PKILL=y -CONFIG_PIDOF=y -CONFIG_FEATURE_PIDOF_SINGLE=y -CONFIG_FEATURE_PIDOF_OMIT=y -CONFIG_PMAP=y -CONFIG_POWERTOP=y -CONFIG_FEATURE_POWERTOP_INTERACTIVE=y -CONFIG_PS=y -# CONFIG_FEATURE_PS_WIDE is not set -# CONFIG_FEATURE_PS_LONG is not set -CONFIG_FEATURE_PS_TIME=y -# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set -CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y -CONFIG_PSTREE=y -CONFIG_PWDX=y -CONFIG_SMEMCAP=y -CONFIG_BB_SYSCTL=y -CONFIG_TOP=y -CONFIG_FEATURE_TOP_INTERACTIVE=y -CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y -CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y -CONFIG_FEATURE_TOP_SMP_CPU=y -# CONFIG_FEATURE_TOP_DECIMALS is not set -CONFIG_FEATURE_TOP_SMP_PROCESS=y -CONFIG_FEATURE_TOPMEM=y -CONFIG_UPTIME=y -# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set -CONFIG_WATCH=y -# CONFIG_FEATURE_SHOW_THREADS is not set - -# -# Runit Utilities -# -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set -# CONFIG_FEATURE_RUNSVDIR_LOG is not set -# CONFIG_SV is not set -CONFIG_SV_DEFAULT_SERVICE_DIR="" -# CONFIG_SVC is not set -# CONFIG_SVLOGD is not set -# CONFIG_CHCON is not set -# CONFIG_GETENFORCE is not set -# CONFIG_GETSEBOOL is not set -# CONFIG_LOAD_POLICY is not set -# CONFIG_MATCHPATHCON is not set -# CONFIG_RUNCON is not set -# CONFIG_SELINUXENABLED is not set -# CONFIG_SESTATUS is not set -# CONFIG_SETENFORCE is not set -# CONFIG_SETFILES is not set -# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set -# CONFIG_RESTORECON is not set -# CONFIG_SETSEBOOL is not set - -# -# Shells -# -CONFIG_SH_IS_ASH=y -# CONFIG_SH_IS_HUSH is not set -# CONFIG_SH_IS_NONE is not set -# CONFIG_BASH_IS_ASH is not set -# CONFIG_BASH_IS_HUSH is not set -CONFIG_BASH_IS_NONE=y -CONFIG_ASH=y -CONFIG_ASH_OPTIMIZE_FOR_SIZE=y -CONFIG_ASH_INTERNAL_GLOB=y -CONFIG_ASH_BASH_COMPAT=y -CONFIG_ASH_JOB_CONTROL=y -CONFIG_ASH_ALIAS=y -CONFIG_ASH_RANDOM_SUPPORT=y -CONFIG_ASH_EXPAND_PRMT=y -CONFIG_ASH_IDLE_TIMEOUT=y -CONFIG_ASH_MAIL=y -CONFIG_ASH_ECHO=y -CONFIG_ASH_PRINTF=y -CONFIG_ASH_TEST=y -CONFIG_ASH_HELP=y -CONFIG_ASH_GETOPTS=y -CONFIG_ASH_CMDCMD=y -CONFIG_ASH_BASH_SOURCE_CURDIR=y -CONFIG_ASH_COMMAND_NOT_FOUND_HOOK=y -# CONFIG_CTTYHACK is not set -# CONFIG_HUSH is not set -# CONFIG_HUSH_BASH_COMPAT is not set -# CONFIG_HUSH_BRACE_EXPANSION is not set -# CONFIG_HUSH_INTERACTIVE is not set -# CONFIG_HUSH_SAVEHISTORY is not set -# CONFIG_HUSH_JOB is not set -# CONFIG_HUSH_TICK is not set -# CONFIG_HUSH_IF is not set -# CONFIG_HUSH_LOOPS is not set -# CONFIG_HUSH_CASE is not set -# CONFIG_HUSH_FUNCTIONS is not set -# CONFIG_HUSH_LOCAL is not set -# CONFIG_HUSH_RANDOM_SUPPORT is not set -# CONFIG_HUSH_MODE_X is not set -# CONFIG_HUSH_ECHO is not set -# CONFIG_HUSH_PRINTF is not set -# CONFIG_HUSH_TEST is not set -# CONFIG_HUSH_HELP is not set -# CONFIG_HUSH_EXPORT is not set -# CONFIG_HUSH_EXPORT_N is not set -# CONFIG_HUSH_READONLY is not set -# CONFIG_HUSH_KILL is not set -# CONFIG_HUSH_WAIT is not set -# CONFIG_HUSH_TRAP is not set -# CONFIG_HUSH_TYPE is not set -# CONFIG_HUSH_TIMES is not set -# CONFIG_HUSH_READ is not set -# CONFIG_HUSH_SET is not set -# CONFIG_HUSH_UNSET is not set -# CONFIG_HUSH_ULIMIT is not set -# CONFIG_HUSH_UMASK is not set -# CONFIG_HUSH_GETOPTS is not set -# CONFIG_HUSH_MEMLEAK is not set - -# -# Options common to all shells -# -CONFIG_FEATURE_SH_MATH=y -CONFIG_FEATURE_SH_MATH_64=y -CONFIG_FEATURE_SH_EXTRA_QUIET=y -# CONFIG_FEATURE_SH_STANDALONE is not set -# CONFIG_FEATURE_SH_NOFORK is not set -CONFIG_FEATURE_SH_READ_FRAC=y -CONFIG_FEATURE_SH_HISTFILESIZE=y - -# -# System Logging Utilities -# -CONFIG_KLOGD=y - -# -# klogd should not be used together with syslog to kernel printk buffer -# -CONFIG_FEATURE_KLOGD_KLOGCTL=y -CONFIG_LOGGER=y -CONFIG_LOGREAD=y -CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y -CONFIG_SYSLOGD=y -CONFIG_FEATURE_ROTATE_LOGFILE=y -CONFIG_FEATURE_REMOTE_LOG=y -CONFIG_FEATURE_SYSLOGD_DUP=y -CONFIG_FEATURE_SYSLOGD_CFG=y -CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256 -CONFIG_FEATURE_IPC_SYSLOG=y -CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16 -CONFIG_FEATURE_KMSG_SYSLOG=y diff --git a/legacy/busybox/busyboxconfig-extras b/legacy/busybox/busyboxconfig-extras deleted file mode 100644 index ed9c572a9..000000000 --- a/legacy/busybox/busyboxconfig-extras +++ /dev/null @@ -1,1131 +0,0 @@ -# -# Automatically generated make config: don't edit -# Busybox version: 1.28.2 -# Wed Mar 28 12:24:25 2018 -# -CONFIG_HAVE_DOT_CONFIG=y - -# -# Settings -# -# CONFIG_DESKTOP is not set -# CONFIG_EXTRA_COMPAT is not set -# CONFIG_FEDORA_COMPAT is not set -# CONFIG_INCLUDE_SUSv2 is not set -# CONFIG_LONG_OPTS is not set -CONFIG_SHOW_USAGE=y -CONFIG_FEATURE_VERBOSE_USAGE=y -CONFIG_FEATURE_COMPRESS_USAGE=y -CONFIG_LFS=y -# CONFIG_PAM is not set -CONFIG_FEATURE_DEVPTS=y -# CONFIG_FEATURE_UTMP is not set -# CONFIG_FEATURE_WTMP is not set -# CONFIG_FEATURE_PIDFILE is not set -CONFIG_PID_FILE_PATH="" -CONFIG_BUSYBOX=y -CONFIG_FEATURE_INSTALLER=y -# CONFIG_INSTALL_NO_USR is not set -# CONFIG_FEATURE_SUID is not set -# CONFIG_FEATURE_SUID_CONFIG is not set -# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set -# CONFIG_FEATURE_PREFER_APPLETS is not set -CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" -# CONFIG_SELINUX is not set -# CONFIG_FEATURE_CLEAN_UP is not set -CONFIG_FEATURE_SYSLOG=y -CONFIG_PLATFORM_LINUX=y - -# -# Build Options -# -# CONFIG_STATIC is not set -CONFIG_PIE=y -# CONFIG_NOMMU is not set -# CONFIG_BUILD_LIBBUSYBOX is not set -# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set -# CONFIG_FEATURE_INDIVIDUAL is not set -# CONFIG_FEATURE_SHARED_BUSYBOX is not set -CONFIG_CROSS_COMPILER_PREFIX="" -CONFIG_SYSROOT="" -CONFIG_EXTRA_CFLAGS="" -CONFIG_EXTRA_LDFLAGS="" -CONFIG_EXTRA_LDLIBS="" -# CONFIG_USE_PORTABLE_CODE is not set - -# -# Installation Options ("make install" behavior) -# -CONFIG_INSTALL_APPLET_SYMLINKS=y -# CONFIG_INSTALL_APPLET_HARDLINKS is not set -# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set -# CONFIG_INSTALL_APPLET_DONT is not set -# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set -# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set -# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set -CONFIG_PREFIX="./_install" - -# -# Debugging Options -# -# CONFIG_DEBUG is not set -# CONFIG_DEBUG_PESSIMIZE is not set -# CONFIG_DEBUG_SANITIZE is not set -# CONFIG_UNIT_TEST is not set -# CONFIG_WERROR is not set -CONFIG_NO_DEBUG_LIB=y -# CONFIG_DMALLOC is not set -# CONFIG_EFENCE is not set - -# -# Library Tuning -# -# CONFIG_FEATURE_USE_BSS_TAIL is not set -# CONFIG_FEATURE_RTMINMAX is not set -CONFIG_FEATURE_BUFFERS_USE_MALLOC=y -# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set -# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set -CONFIG_PASSWORD_MINLEN=6 -CONFIG_MD5_SMALL=1 -CONFIG_SHA3_SMALL=1 -# CONFIG_FEATURE_FAST_TOP is not set -# CONFIG_FEATURE_ETC_NETWORKS is not set -# CONFIG_FEATURE_EDITING is not set -CONFIG_FEATURE_EDITING_MAX_LEN=0 -# CONFIG_FEATURE_EDITING_VI is not set -CONFIG_FEATURE_EDITING_HISTORY=0 -# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set -# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set -# CONFIG_FEATURE_REVERSE_SEARCH is not set -# CONFIG_FEATURE_TAB_COMPLETION is not set -# CONFIG_FEATURE_USERNAME_COMPLETION is not set -# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set -# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set -# CONFIG_LOCALE_SUPPORT is not set -# CONFIG_UNICODE_SUPPORT is not set -# CONFIG_UNICODE_USING_LOCALE is not set -# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set -CONFIG_SUBST_WCHAR=0 -CONFIG_LAST_SUPPORTED_WCHAR=0 -# CONFIG_UNICODE_COMBINING_WCHARS is not set -# CONFIG_UNICODE_WIDE_WCHARS is not set -# CONFIG_UNICODE_BIDI_SUPPORT is not set -# CONFIG_UNICODE_NEUTRAL_TABLE is not set -# CONFIG_UNICODE_PRESERVE_BROKEN is not set -# CONFIG_FEATURE_NON_POSIX_CP is not set -# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set -# CONFIG_FEATURE_USE_SENDFILE is not set -CONFIG_FEATURE_COPYBUF_KB=4 -# CONFIG_FEATURE_SKIP_ROOTFS is not set -# CONFIG_MONOTONIC_SYSCALL is not set -# CONFIG_IOCTL_HEX2STR_ERROR is not set -# CONFIG_FEATURE_HWIB is not set - -# -# Applets -# - -# -# Archival Utilities -# -# CONFIG_FEATURE_SEAMLESS_XZ is not set -# CONFIG_FEATURE_SEAMLESS_LZMA is not set -# CONFIG_FEATURE_SEAMLESS_BZ2 is not set -CONFIG_FEATURE_SEAMLESS_GZ=y -# CONFIG_FEATURE_SEAMLESS_Z is not set -# CONFIG_AR is not set -# CONFIG_FEATURE_AR_LONG_FILENAMES is not set -# CONFIG_FEATURE_AR_CREATE is not set -# CONFIG_UNCOMPRESS is not set -# CONFIG_GUNZIP is not set -# CONFIG_ZCAT is not set -# CONFIG_FEATURE_GUNZIP_LONG_OPTIONS is not set -# CONFIG_BUNZIP2 is not set -# CONFIG_BZCAT is not set -# CONFIG_UNLZMA is not set -# CONFIG_LZCAT is not set -# CONFIG_LZMA is not set -# CONFIG_UNXZ is not set -# CONFIG_XZCAT is not set -# CONFIG_XZ is not set -# CONFIG_BZIP2 is not set -# CONFIG_FEATURE_BZIP2_DECOMPRESS is not set -# CONFIG_CPIO is not set -# CONFIG_FEATURE_CPIO_O is not set -# CONFIG_FEATURE_CPIO_P is not set -# CONFIG_DPKG is not set -# CONFIG_DPKG_DEB is not set -# CONFIG_GZIP is not set -# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set -CONFIG_GZIP_FAST=0 -# CONFIG_FEATURE_GZIP_LEVELS is not set -# CONFIG_FEATURE_GZIP_DECOMPRESS is not set -# CONFIG_LZOP is not set -# CONFIG_UNLZOP is not set -# CONFIG_LZOPCAT is not set -# CONFIG_LZOP_COMPR_HIGH is not set -# CONFIG_RPM is not set -# CONFIG_RPM2CPIO is not set -# CONFIG_TAR is not set -# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set -# CONFIG_FEATURE_TAR_CREATE is not set -# CONFIG_FEATURE_TAR_AUTODETECT is not set -# CONFIG_FEATURE_TAR_FROM is not set -# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set -# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set -# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set -# CONFIG_FEATURE_TAR_TO_COMMAND is not set -# CONFIG_FEATURE_TAR_UNAME_GNAME is not set -# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set -# CONFIG_FEATURE_TAR_SELINUX is not set -# CONFIG_UNZIP is not set -# CONFIG_FEATURE_UNZIP_CDF is not set -# CONFIG_FEATURE_UNZIP_BZIP2 is not set -# CONFIG_FEATURE_UNZIP_LZMA is not set -# CONFIG_FEATURE_UNZIP_XZ is not set -# CONFIG_FEATURE_LZMA_FAST is not set - -# -# Coreutils -# -# CONFIG_BASENAME is not set -# CONFIG_CAT is not set -# CONFIG_FEATURE_CATN is not set -# CONFIG_FEATURE_CATV is not set -# CONFIG_CHGRP is not set -# CONFIG_CHMOD is not set -# CONFIG_CHOWN is not set -# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set -# CONFIG_CHROOT is not set -# CONFIG_CKSUM is not set -# CONFIG_COMM is not set -# CONFIG_CP is not set -# CONFIG_FEATURE_CP_LONG_OPTIONS is not set -# CONFIG_CUT is not set -# CONFIG_DATE is not set -# CONFIG_FEATURE_DATE_ISOFMT is not set -# CONFIG_FEATURE_DATE_NANO is not set -# CONFIG_FEATURE_DATE_COMPAT is not set -# CONFIG_DD is not set -# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set -# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set -# CONFIG_FEATURE_DD_IBS_OBS is not set -# CONFIG_FEATURE_DD_STATUS is not set -# CONFIG_DF is not set -# CONFIG_FEATURE_DF_FANCY is not set -# CONFIG_DIRNAME is not set -# CONFIG_DOS2UNIX is not set -# CONFIG_UNIX2DOS is not set -# CONFIG_DU is not set -# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set -# CONFIG_ECHO is not set -# CONFIG_FEATURE_FANCY_ECHO is not set -# CONFIG_ENV is not set -# CONFIG_EXPAND is not set -# CONFIG_UNEXPAND is not set -# CONFIG_EXPR is not set -# CONFIG_EXPR_MATH_SUPPORT_64 is not set -# CONFIG_FACTOR is not set -# CONFIG_FALSE is not set -# CONFIG_FOLD is not set -# CONFIG_FSYNC is not set -# CONFIG_HEAD is not set -# CONFIG_FEATURE_FANCY_HEAD is not set -# CONFIG_HOSTID is not set -# CONFIG_ID is not set -# CONFIG_GROUPS is not set -# CONFIG_INSTALL is not set -# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set -# CONFIG_LINK is not set -# CONFIG_LN is not set -# CONFIG_LOGNAME is not set -# CONFIG_LS is not set -# CONFIG_FEATURE_LS_FILETYPES is not set -# CONFIG_FEATURE_LS_FOLLOWLINKS is not set -# CONFIG_FEATURE_LS_RECURSIVE is not set -# CONFIG_FEATURE_LS_WIDTH is not set -# CONFIG_FEATURE_LS_SORTFILES is not set -# CONFIG_FEATURE_LS_TIMESTAMPS is not set -# CONFIG_FEATURE_LS_USERNAME is not set -# CONFIG_FEATURE_LS_COLOR is not set -# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set -# CONFIG_MD5SUM is not set -# CONFIG_SHA1SUM is not set -# CONFIG_SHA256SUM is not set -# CONFIG_SHA512SUM is not set -# CONFIG_SHA3SUM is not set -# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set -# CONFIG_MKDIR is not set -# CONFIG_MKFIFO is not set -# CONFIG_MKNOD is not set -# CONFIG_MKTEMP is not set -# CONFIG_MV is not set -# CONFIG_NICE is not set -# CONFIG_NL is not set -# CONFIG_NOHUP is not set -# CONFIG_NPROC is not set -# CONFIG_OD is not set -# CONFIG_PASTE is not set -# CONFIG_PRINTENV is not set -# CONFIG_PRINTF is not set -# CONFIG_PWD is not set -# CONFIG_READLINK is not set -# CONFIG_FEATURE_READLINK_FOLLOW is not set -# CONFIG_REALPATH is not set -# CONFIG_RM is not set -# CONFIG_RMDIR is not set -# CONFIG_SEQ is not set -# CONFIG_SHRED is not set -# CONFIG_SHUF is not set -# CONFIG_SLEEP is not set -# CONFIG_FEATURE_FANCY_SLEEP is not set -# CONFIG_FEATURE_FLOAT_SLEEP is not set -# CONFIG_SORT is not set -# CONFIG_FEATURE_SORT_BIG is not set -# CONFIG_SPLIT is not set -# CONFIG_FEATURE_SPLIT_FANCY is not set -# CONFIG_STAT is not set -# CONFIG_FEATURE_STAT_FORMAT is not set -# CONFIG_FEATURE_STAT_FILESYSTEM is not set -# CONFIG_STTY is not set -# CONFIG_SUM is not set -# CONFIG_SYNC is not set -# CONFIG_FEATURE_SYNC_FANCY is not set -# CONFIG_TAC is not set -# CONFIG_TAIL is not set -# CONFIG_FEATURE_FANCY_TAIL is not set -# CONFIG_TEE is not set -# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set -# CONFIG_TEST is not set -# CONFIG_TEST1 is not set -# CONFIG_TEST2 is not set -# CONFIG_FEATURE_TEST_64 is not set -# CONFIG_TIMEOUT is not set -# CONFIG_TOUCH is not set -# CONFIG_FEATURE_TOUCH_NODEREF is not set -# CONFIG_FEATURE_TOUCH_SUSV3 is not set -# CONFIG_TR is not set -# CONFIG_FEATURE_TR_CLASSES is not set -# CONFIG_FEATURE_TR_EQUIV is not set -# CONFIG_TRUE is not set -# CONFIG_TRUNCATE is not set -# CONFIG_TTY is not set -# CONFIG_UNAME is not set -CONFIG_UNAME_OSNAME="" -CONFIG_BB_ARCH=y -# CONFIG_UNIQ is not set -# CONFIG_UNLINK is not set -# CONFIG_USLEEP is not set -# CONFIG_UUDECODE is not set -# CONFIG_BASE64 is not set -# CONFIG_UUENCODE is not set -# CONFIG_WC is not set -# CONFIG_FEATURE_WC_LARGE is not set -# CONFIG_WHO is not set -# CONFIG_W is not set -# CONFIG_USERS is not set -# CONFIG_WHOAMI is not set -# CONFIG_YES is not set - -# -# Common options -# -# CONFIG_FEATURE_VERBOSE is not set -# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set -# CONFIG_FEATURE_HUMAN_READABLE is not set - -# -# Console Utilities -# -# CONFIG_CHVT is not set -# CONFIG_CLEAR is not set -# CONFIG_DEALLOCVT is not set -# CONFIG_DUMPKMAP is not set -# CONFIG_FGCONSOLE is not set -# CONFIG_KBD_MODE is not set -# CONFIG_LOADFONT is not set -# CONFIG_SETFONT is not set -# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set -CONFIG_DEFAULT_SETFONT_DIR="" -# CONFIG_FEATURE_LOADFONT_PSF2 is not set -# CONFIG_FEATURE_LOADFONT_RAW is not set -# CONFIG_LOADKMAP is not set -# CONFIG_OPENVT is not set -# CONFIG_RESET is not set -# CONFIG_RESIZE is not set -# CONFIG_FEATURE_RESIZE_PRINT is not set -# CONFIG_SETCONSOLE is not set -# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set -# CONFIG_SETKEYCODES is not set -# CONFIG_SETLOGCONS is not set -# CONFIG_SHOWKEY is not set - -# -# Debian Utilities -# -# CONFIG_PIPE_PROGRESS is not set -# CONFIG_RUN_PARTS is not set -# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set -# CONFIG_FEATURE_RUN_PARTS_FANCY is not set -# CONFIG_START_STOP_DAEMON is not set -# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set -# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set -# CONFIG_WHICH is not set - -# -# klibc-utils -# -# CONFIG_MINIPS is not set -# CONFIG_NUKE is not set -# CONFIG_RESUME is not set -# CONFIG_RUN_INIT is not set - -# -# Editors -# -# CONFIG_AWK is not set -# CONFIG_FEATURE_AWK_LIBM is not set -# CONFIG_FEATURE_AWK_GNU_EXTENSIONS is not set -# CONFIG_CMP is not set -# CONFIG_DIFF is not set -# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set -# CONFIG_FEATURE_DIFF_DIR is not set -# CONFIG_ED is not set -# CONFIG_PATCH is not set -# CONFIG_SED is not set -# CONFIG_VI is not set -CONFIG_FEATURE_VI_MAX_LEN=0 -# CONFIG_FEATURE_VI_8BIT is not set -# CONFIG_FEATURE_VI_COLON is not set -# CONFIG_FEATURE_VI_YANKMARK is not set -# CONFIG_FEATURE_VI_SEARCH is not set -# CONFIG_FEATURE_VI_REGEX_SEARCH is not set -# CONFIG_FEATURE_VI_USE_SIGNALS is not set -# CONFIG_FEATURE_VI_DOT_CMD is not set -# CONFIG_FEATURE_VI_READONLY is not set -# CONFIG_FEATURE_VI_SETOPTS is not set -# CONFIG_FEATURE_VI_SET is not set -# CONFIG_FEATURE_VI_WIN_RESIZE is not set -# CONFIG_FEATURE_VI_ASK_TERMINAL is not set -# CONFIG_FEATURE_VI_UNDO is not set -# CONFIG_FEATURE_VI_UNDO_QUEUE is not set -CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=0 -# CONFIG_FEATURE_ALLOW_EXEC is not set - -# -# Finding Utilities -# -# CONFIG_FIND is not set -# CONFIG_FEATURE_FIND_PRINT0 is not set -# CONFIG_FEATURE_FIND_MTIME is not set -# CONFIG_FEATURE_FIND_MMIN is not set -# CONFIG_FEATURE_FIND_PERM is not set -# CONFIG_FEATURE_FIND_TYPE is not set -# CONFIG_FEATURE_FIND_XDEV is not set -# CONFIG_FEATURE_FIND_MAXDEPTH is not set -# CONFIG_FEATURE_FIND_NEWER is not set -# CONFIG_FEATURE_FIND_INUM is not set -# CONFIG_FEATURE_FIND_EXEC is not set -# CONFIG_FEATURE_FIND_EXEC_PLUS is not set -# CONFIG_FEATURE_FIND_USER is not set -# CONFIG_FEATURE_FIND_GROUP is not set -# CONFIG_FEATURE_FIND_NOT is not set -# CONFIG_FEATURE_FIND_DEPTH is not set -# CONFIG_FEATURE_FIND_PAREN is not set -# CONFIG_FEATURE_FIND_SIZE is not set -# CONFIG_FEATURE_FIND_PRUNE is not set -# CONFIG_FEATURE_FIND_DELETE is not set -# CONFIG_FEATURE_FIND_PATH is not set -# CONFIG_FEATURE_FIND_REGEX is not set -# CONFIG_FEATURE_FIND_CONTEXT is not set -# CONFIG_FEATURE_FIND_LINKS is not set -# CONFIG_GREP is not set -# CONFIG_EGREP is not set -# CONFIG_FGREP is not set -# CONFIG_FEATURE_GREP_CONTEXT is not set -# CONFIG_XARGS is not set -# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set -# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set -# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set -# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set -# CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR is not set -# CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL is not set -# CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE is not set - -# -# Init Utilities -# -# CONFIG_BOOTCHARTD is not set -# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set -# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set -# CONFIG_HALT is not set -# CONFIG_POWEROFF is not set -# CONFIG_REBOOT is not set -# CONFIG_FEATURE_CALL_TELINIT is not set -CONFIG_TELINIT_PATH="" -# CONFIG_INIT is not set -# CONFIG_LINUXRC is not set -# CONFIG_FEATURE_USE_INITTAB is not set -# CONFIG_FEATURE_KILL_REMOVED is not set -CONFIG_FEATURE_KILL_DELAY=0 -# CONFIG_FEATURE_INIT_SCTTY is not set -# CONFIG_FEATURE_INIT_SYSLOG is not set -# CONFIG_FEATURE_INIT_QUIET is not set -# CONFIG_FEATURE_INIT_COREDUMPS is not set -CONFIG_INIT_TERMINAL_TYPE="" -# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set - -# -# Login/Password Management Utilities -# -# CONFIG_FEATURE_SHADOWPASSWDS is not set -# CONFIG_USE_BB_PWD_GRP is not set -# CONFIG_USE_BB_SHADOW is not set -# CONFIG_USE_BB_CRYPT is not set -# CONFIG_USE_BB_CRYPT_SHA is not set -# CONFIG_ADD_SHELL is not set -# CONFIG_REMOVE_SHELL is not set -# CONFIG_ADDGROUP is not set -# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set -# CONFIG_ADDUSER is not set -# CONFIG_FEATURE_CHECK_NAMES is not set -CONFIG_LAST_ID=0 -CONFIG_FIRST_SYSTEM_ID=0 -CONFIG_LAST_SYSTEM_ID=0 -# CONFIG_CHPASSWD is not set -CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="" -# CONFIG_CRYPTPW is not set -# CONFIG_MKPASSWD is not set -# CONFIG_DELUSER is not set -# CONFIG_DELGROUP is not set -# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set -# CONFIG_GETTY is not set -# CONFIG_LOGIN is not set -# CONFIG_LOGIN_SESSION_AS_CHILD is not set -# CONFIG_LOGIN_SCRIPTS is not set -# CONFIG_FEATURE_NOLOGIN is not set -# CONFIG_FEATURE_SECURETTY is not set -# CONFIG_NOLOGIN is not set -# CONFIG_PASSWD is not set -# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set -# CONFIG_SU is not set -# CONFIG_FEATURE_SU_SYSLOG is not set -# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set -# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set -# CONFIG_SULOGIN is not set -# CONFIG_VLOCK is not set - -# -# Linux Ext2 FS Progs -# -# CONFIG_CHATTR is not set -# CONFIG_FSCK is not set -# CONFIG_LSATTR is not set -# CONFIG_TUNE2FS is not set - -# -# Linux Module Utilities -# -# CONFIG_MODPROBE_SMALL is not set -# CONFIG_DEPMOD is not set -# CONFIG_INSMOD is not set -# CONFIG_LSMOD is not set -# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set -# CONFIG_MODINFO is not set -# CONFIG_MODPROBE is not set -# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set -# CONFIG_RMMOD is not set - -# -# Options common to multiple modutils -# -# CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS is not set -# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set -# CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set -# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set -# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set -# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set -# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_BIN is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set -CONFIG_DEFAULT_MODULES_DIR="" -CONFIG_DEFAULT_DEPMOD_FILE="" - -# -# Linux System Utilities -# -# CONFIG_ACPID is not set -# CONFIG_FEATURE_ACPID_COMPAT is not set -# CONFIG_BLKDISCARD is not set -# CONFIG_BLKID is not set -# CONFIG_FEATURE_BLKID_TYPE is not set -# CONFIG_BLOCKDEV is not set -# CONFIG_CAL is not set -# CONFIG_CHRT is not set -# CONFIG_DMESG is not set -# CONFIG_FEATURE_DMESG_PRETTY is not set -# CONFIG_EJECT is not set -# CONFIG_FEATURE_EJECT_SCSI is not set -# CONFIG_FALLOCATE is not set -# CONFIG_FATATTR is not set -# CONFIG_FBSET is not set -# CONFIG_FEATURE_FBSET_FANCY is not set -# CONFIG_FEATURE_FBSET_READMODE is not set -# CONFIG_FDFORMAT is not set -# CONFIG_FDISK is not set -# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set -# CONFIG_FEATURE_FDISK_WRITABLE is not set -# CONFIG_FEATURE_AIX_LABEL is not set -# CONFIG_FEATURE_SGI_LABEL is not set -# CONFIG_FEATURE_SUN_LABEL is not set -# CONFIG_FEATURE_OSF_LABEL is not set -# CONFIG_FEATURE_GPT_LABEL is not set -# CONFIG_FEATURE_FDISK_ADVANCED is not set -# CONFIG_FINDFS is not set -# CONFIG_FLOCK is not set -# CONFIG_FDFLUSH is not set -# CONFIG_FREERAMDISK is not set -# CONFIG_FSCK_MINIX is not set -# CONFIG_FSFREEZE is not set -# CONFIG_FSTRIM is not set -# CONFIG_GETOPT is not set -# CONFIG_FEATURE_GETOPT_LONG is not set -# CONFIG_HEXDUMP is not set -# CONFIG_FEATURE_HEXDUMP_REVERSE is not set -# CONFIG_HD is not set -# CONFIG_XXD is not set -# CONFIG_HWCLOCK is not set -# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set -# CONFIG_IONICE is not set -# CONFIG_IPCRM is not set -# CONFIG_IPCS is not set -# CONFIG_LAST is not set -# CONFIG_FEATURE_LAST_FANCY is not set -# CONFIG_LOSETUP is not set -# CONFIG_LSPCI is not set -# CONFIG_LSUSB is not set -# CONFIG_MDEV is not set -# CONFIG_FEATURE_MDEV_CONF is not set -# CONFIG_FEATURE_MDEV_RENAME is not set -# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set -# CONFIG_FEATURE_MDEV_EXEC is not set -# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set -# CONFIG_MESG is not set -# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set -# CONFIG_MKE2FS is not set -# CONFIG_MKFS_EXT2 is not set -# CONFIG_MKFS_MINIX is not set -# CONFIG_FEATURE_MINIX2 is not set -# CONFIG_MKFS_REISER is not set -# CONFIG_MKDOSFS is not set -# CONFIG_MKFS_VFAT is not set -# CONFIG_MKSWAP is not set -# CONFIG_FEATURE_MKSWAP_UUID is not set -# CONFIG_MORE is not set -# CONFIG_MOUNT is not set -# CONFIG_FEATURE_MOUNT_FAKE is not set -# CONFIG_FEATURE_MOUNT_VERBOSE is not set -# CONFIG_FEATURE_MOUNT_HELPERS is not set -# CONFIG_FEATURE_MOUNT_LABEL is not set -# CONFIG_FEATURE_MOUNT_NFS is not set -# CONFIG_FEATURE_MOUNT_CIFS is not set -# CONFIG_FEATURE_MOUNT_FLAGS is not set -# CONFIG_FEATURE_MOUNT_FSTAB is not set -# CONFIG_FEATURE_MOUNT_OTHERTAB is not set -# CONFIG_MOUNTPOINT is not set -# CONFIG_NSENTER is not set -# CONFIG_PIVOT_ROOT is not set -# CONFIG_RDATE is not set -# CONFIG_RDEV is not set -# CONFIG_READPROFILE is not set -# CONFIG_RENICE is not set -# CONFIG_REV is not set -# CONFIG_RTCWAKE is not set -# CONFIG_SCRIPT is not set -# CONFIG_SCRIPTREPLAY is not set -# CONFIG_SETARCH is not set -# CONFIG_LINUX32 is not set -# CONFIG_LINUX64 is not set -# CONFIG_SETPRIV is not set -# CONFIG_FEATURE_SETPRIV_DUMP is not set -# CONFIG_FEATURE_SETPRIV_CAPABILITIES is not set -# CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES is not set -# CONFIG_SETSID is not set -# CONFIG_SWAPON is not set -# CONFIG_FEATURE_SWAPON_DISCARD is not set -# CONFIG_FEATURE_SWAPON_PRI is not set -# CONFIG_SWAPOFF is not set -# CONFIG_FEATURE_SWAPONOFF_LABEL is not set -# CONFIG_SWITCH_ROOT is not set -# CONFIG_TASKSET is not set -# CONFIG_FEATURE_TASKSET_FANCY is not set -# CONFIG_UEVENT is not set -# CONFIG_UMOUNT is not set -# CONFIG_FEATURE_UMOUNT_ALL is not set -# CONFIG_UNSHARE is not set -# CONFIG_WALL is not set -# CONFIG_FEATURE_MOUNT_LOOP is not set -# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set -# CONFIG_FEATURE_MTAB_SUPPORT is not set -# CONFIG_VOLUMEID is not set -# CONFIG_FEATURE_VOLUMEID_BCACHE is not set -# CONFIG_FEATURE_VOLUMEID_BTRFS is not set -# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set -# CONFIG_FEATURE_VOLUMEID_EXFAT is not set -# CONFIG_FEATURE_VOLUMEID_EXT is not set -# CONFIG_FEATURE_VOLUMEID_F2FS is not set -# CONFIG_FEATURE_VOLUMEID_FAT is not set -# CONFIG_FEATURE_VOLUMEID_HFS is not set -# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set -# CONFIG_FEATURE_VOLUMEID_JFS is not set -# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set -# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set -# CONFIG_FEATURE_VOLUMEID_LUKS is not set -# CONFIG_FEATURE_VOLUMEID_MINIX is not set -# CONFIG_FEATURE_VOLUMEID_NILFS is not set -# CONFIG_FEATURE_VOLUMEID_NTFS is not set -# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set -# CONFIG_FEATURE_VOLUMEID_REISERFS is not set -# CONFIG_FEATURE_VOLUMEID_ROMFS is not set -# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set -# CONFIG_FEATURE_VOLUMEID_SYSV is not set -# CONFIG_FEATURE_VOLUMEID_UBIFS is not set -# CONFIG_FEATURE_VOLUMEID_UDF is not set -# CONFIG_FEATURE_VOLUMEID_XFS is not set - -# -# Miscellaneous Utilities -# -# CONFIG_ADJTIMEX is not set -# CONFIG_BBCONFIG is not set -# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set -# CONFIG_BEEP is not set -CONFIG_FEATURE_BEEP_FREQ=0 -CONFIG_FEATURE_BEEP_LENGTH_MS=0 -# CONFIG_CHAT is not set -# CONFIG_FEATURE_CHAT_NOFAIL is not set -# CONFIG_FEATURE_CHAT_TTY_HIFI is not set -# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set -# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set -# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set -# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set -# CONFIG_FEATURE_CHAT_CLR_ABORT is not set -# CONFIG_CONSPY is not set -# CONFIG_CROND is not set -# CONFIG_FEATURE_CROND_D is not set -# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set -# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set -CONFIG_FEATURE_CROND_DIR="" -# CONFIG_CRONTAB is not set -# CONFIG_DC is not set -# CONFIG_FEATURE_DC_LIBM is not set -# CONFIG_DEVFSD is not set -# CONFIG_DEVFSD_MODLOAD is not set -# CONFIG_DEVFSD_FG_NP is not set -# CONFIG_DEVFSD_VERBOSE is not set -# CONFIG_FEATURE_DEVFS is not set -# CONFIG_DEVMEM is not set -# CONFIG_FBSPLASH is not set -# CONFIG_FLASH_ERASEALL is not set -# CONFIG_FLASH_LOCK is not set -# CONFIG_FLASH_UNLOCK is not set -# CONFIG_FLASHCP is not set -# CONFIG_HDPARM is not set -# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set -# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set -# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set -# CONFIG_HEXEDIT is not set -# CONFIG_I2CGET is not set -# CONFIG_I2CSET is not set -# CONFIG_I2CDUMP is not set -# CONFIG_I2CDETECT is not set -# CONFIG_INOTIFYD is not set -# CONFIG_LESS is not set -CONFIG_FEATURE_LESS_MAXLINES=0 -# CONFIG_FEATURE_LESS_BRACKETS is not set -# CONFIG_FEATURE_LESS_FLAGS is not set -# CONFIG_FEATURE_LESS_TRUNCATE is not set -# CONFIG_FEATURE_LESS_MARKS is not set -# CONFIG_FEATURE_LESS_REGEXP is not set -# CONFIG_FEATURE_LESS_WINCH is not set -# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set -# CONFIG_FEATURE_LESS_DASHCMD is not set -# CONFIG_FEATURE_LESS_LINENUMS is not set -# CONFIG_LSSCSI is not set -# CONFIG_MAKEDEVS is not set -# CONFIG_FEATURE_MAKEDEVS_LEAF is not set -# CONFIG_FEATURE_MAKEDEVS_TABLE is not set -# CONFIG_MAN is not set -# CONFIG_MICROCOM is not set -# CONFIG_MT is not set -# CONFIG_NANDWRITE is not set -# CONFIG_NANDDUMP is not set -# CONFIG_PARTPROBE is not set -# CONFIG_RAIDAUTORUN is not set -CONFIG_READAHEAD=y -# CONFIG_RFKILL is not set -# CONFIG_RUNLEVEL is not set -# CONFIG_RX is not set -# CONFIG_SETFATTR is not set -# CONFIG_SETSERIAL is not set -# CONFIG_STRINGS is not set -# CONFIG_TIME is not set -# CONFIG_TTYSIZE is not set -# CONFIG_UBIATTACH is not set -# CONFIG_UBIDETACH is not set -# CONFIG_UBIMKVOL is not set -# CONFIG_UBIRMVOL is not set -# CONFIG_UBIRSVOL is not set -# CONFIG_UBIUPDATEVOL is not set -# CONFIG_UBIRENAME is not set -# CONFIG_VOLNAME is not set -# CONFIG_WATCHDOG is not set - -# -# Networking Utilities -# -# CONFIG_FEATURE_IPV6 is not set -# CONFIG_FEATURE_UNIX_LOCAL is not set -# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set -# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set -# CONFIG_ARP is not set -# CONFIG_ARPING is not set -# CONFIG_BRCTL is not set -# CONFIG_FEATURE_BRCTL_FANCY is not set -# CONFIG_FEATURE_BRCTL_SHOW is not set -CONFIG_DNSD=y -# CONFIG_ETHER_WAKE is not set -CONFIG_FTPD=y -CONFIG_FEATURE_FTPD_WRITE=y -CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y -CONFIG_FEATURE_FTPD_AUTHENTICATION=y -CONFIG_FTPGET=y -CONFIG_FTPPUT=y -# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set -# CONFIG_HOSTNAME is not set -# CONFIG_DNSDOMAINNAME is not set -CONFIG_HTTPD=y -CONFIG_FEATURE_HTTPD_RANGES=y -CONFIG_FEATURE_HTTPD_SETUID=y -CONFIG_FEATURE_HTTPD_BASIC_AUTH=y -CONFIG_FEATURE_HTTPD_AUTH_MD5=y -CONFIG_FEATURE_HTTPD_CGI=y -CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y -CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y -CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y -CONFIG_FEATURE_HTTPD_ERROR_PAGES=y -CONFIG_FEATURE_HTTPD_PROXY=y -CONFIG_FEATURE_HTTPD_GZIP=y -# CONFIG_IFCONFIG is not set -# CONFIG_FEATURE_IFCONFIG_STATUS is not set -# CONFIG_FEATURE_IFCONFIG_SLIP is not set -# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set -# CONFIG_FEATURE_IFCONFIG_HW is not set -# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set -# CONFIG_IFENSLAVE is not set -# CONFIG_IFPLUGD is not set -# CONFIG_IFUP is not set -# CONFIG_IFDOWN is not set -CONFIG_IFUPDOWN_IFSTATE_PATH="" -# CONFIG_FEATURE_IFUPDOWN_IP is not set -# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set -# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set -# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set -# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set -CONFIG_INETD=y -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set -# CONFIG_FEATURE_INETD_RPC is not set -# CONFIG_IP is not set -# CONFIG_IPADDR is not set -# CONFIG_IPLINK is not set -# CONFIG_IPROUTE is not set -# CONFIG_IPTUNNEL is not set -# CONFIG_IPRULE is not set -# CONFIG_IPNEIGH is not set -# CONFIG_FEATURE_IP_ADDRESS is not set -# CONFIG_FEATURE_IP_LINK is not set -# CONFIG_FEATURE_IP_ROUTE is not set -CONFIG_FEATURE_IP_ROUTE_DIR="" -# CONFIG_FEATURE_IP_TUNNEL is not set -# CONFIG_FEATURE_IP_RULE is not set -# CONFIG_FEATURE_IP_NEIGH is not set -# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set -# CONFIG_IPCALC is not set -# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set -# CONFIG_FEATURE_IPCALC_FANCY is not set -CONFIG_FAKEIDENTD=y -# CONFIG_NAMEIF is not set -# CONFIG_FEATURE_NAMEIF_EXTENDED is not set -# CONFIG_NBDCLIENT is not set -# CONFIG_NC is not set -# CONFIG_NETCAT is not set -# CONFIG_NC_SERVER is not set -# CONFIG_NC_EXTRA is not set -# CONFIG_NC_110_COMPAT is not set -# CONFIG_NETSTAT is not set -# CONFIG_FEATURE_NETSTAT_WIDE is not set -# CONFIG_FEATURE_NETSTAT_PRG is not set -# CONFIG_NSLOOKUP is not set -# CONFIG_NTPD is not set -# CONFIG_FEATURE_NTPD_SERVER is not set -# CONFIG_FEATURE_NTPD_CONF is not set -# CONFIG_PING is not set -# CONFIG_PING6 is not set -# CONFIG_FEATURE_FANCY_PING is not set -# CONFIG_PSCAN is not set -# CONFIG_ROUTE is not set -# CONFIG_SLATTACH is not set -# CONFIG_SSL_CLIENT is not set -# CONFIG_TCPSVD is not set -# CONFIG_UDPSVD is not set -CONFIG_TELNET=y -CONFIG_FEATURE_TELNET_TTYPE=y -CONFIG_FEATURE_TELNET_AUTOLOGIN=y -CONFIG_FEATURE_TELNET_WIDTH=y -CONFIG_TELNETD=y -CONFIG_FEATURE_TELNETD_STANDALONE=y -CONFIG_FEATURE_TELNETD_INETD_WAIT=y -CONFIG_TFTP=y -CONFIG_FEATURE_TFTP_PROGRESS_BAR=y -CONFIG_TFTPD=y - -# -# Common options for tftp/tftpd -# -CONFIG_FEATURE_TFTP_GET=y -CONFIG_FEATURE_TFTP_PUT=y -CONFIG_FEATURE_TFTP_BLOCKSIZE=y -# CONFIG_TFTP_DEBUG is not set -# CONFIG_TLS is not set -# CONFIG_TRACEROUTE is not set -# CONFIG_TRACEROUTE6 is not set -# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set -# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set -# CONFIG_TUNCTL is not set -# CONFIG_FEATURE_TUNCTL_UG is not set -# CONFIG_VCONFIG is not set -# CONFIG_WGET is not set -# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set -# CONFIG_FEATURE_WGET_STATUSBAR is not set -# CONFIG_FEATURE_WGET_AUTHENTICATION is not set -# CONFIG_FEATURE_WGET_TIMEOUT is not set -# CONFIG_FEATURE_WGET_HTTPS is not set -# CONFIG_FEATURE_WGET_OPENSSL is not set -# CONFIG_WHOIS is not set -# CONFIG_ZCIP is not set -CONFIG_UDHCPD=y -CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC=y -CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y -CONFIG_DHCPD_LEASES_FILE="/var/lib/udhcpd/udhcpd.leases" -# CONFIG_DUMPLEASES is not set -# CONFIG_DHCPRELAY is not set -# CONFIG_UDHCPC is not set -# CONFIG_FEATURE_UDHCPC_ARPING is not set -# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set -CONFIG_UDHCPC_DEFAULT_SCRIPT="" -# CONFIG_UDHCPC6 is not set -# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set -# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set -# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set - -# -# Common options for DHCP applets -# -# CONFIG_FEATURE_UDHCP_PORT is not set -CONFIG_UDHCP_DEBUG=0 -CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 -CONFIG_FEATURE_UDHCP_RFC3397=y -CONFIG_FEATURE_UDHCP_8021Q=y -CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" - -# -# Print Utilities -# -# CONFIG_LPD is not set -# CONFIG_LPR is not set -# CONFIG_LPQ is not set - -# -# Mail Utilities -# -# CONFIG_MAKEMIME is not set -# CONFIG_POPMAILDIR is not set -# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set -# CONFIG_REFORMIME is not set -# CONFIG_FEATURE_REFORMIME_COMPAT is not set -# CONFIG_SENDMAIL is not set -CONFIG_FEATURE_MIME_CHARSET="" - -# -# Process Utilities -# -# CONFIG_FREE is not set -# CONFIG_FUSER is not set -# CONFIG_IOSTAT is not set -# CONFIG_KILL is not set -# CONFIG_KILLALL is not set -# CONFIG_KILLALL5 is not set -# CONFIG_LSOF is not set -# CONFIG_MPSTAT is not set -# CONFIG_NMETER is not set -# CONFIG_PGREP is not set -# CONFIG_PKILL is not set -# CONFIG_PIDOF is not set -# CONFIG_FEATURE_PIDOF_SINGLE is not set -# CONFIG_FEATURE_PIDOF_OMIT is not set -# CONFIG_PMAP is not set -# CONFIG_POWERTOP is not set -# CONFIG_FEATURE_POWERTOP_INTERACTIVE is not set -# CONFIG_PS is not set -# CONFIG_FEATURE_PS_WIDE is not set -# CONFIG_FEATURE_PS_LONG is not set -# CONFIG_FEATURE_PS_TIME is not set -# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set -# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set -# CONFIG_PSTREE is not set -# CONFIG_PWDX is not set -# CONFIG_SMEMCAP is not set -# CONFIG_BB_SYSCTL is not set -# CONFIG_TOP is not set -# CONFIG_FEATURE_TOP_INTERACTIVE is not set -# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set -# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set -# CONFIG_FEATURE_TOP_SMP_CPU is not set -# CONFIG_FEATURE_TOP_DECIMALS is not set -# CONFIG_FEATURE_TOP_SMP_PROCESS is not set -# CONFIG_FEATURE_TOPMEM is not set -# CONFIG_UPTIME is not set -# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set -# CONFIG_WATCH is not set -# CONFIG_FEATURE_SHOW_THREADS is not set - -# -# Runit Utilities -# -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set -# CONFIG_FEATURE_RUNSVDIR_LOG is not set -# CONFIG_SV is not set -CONFIG_SV_DEFAULT_SERVICE_DIR="" -# CONFIG_SVC is not set -# CONFIG_SVLOGD is not set -# CONFIG_CHCON is not set -# CONFIG_GETENFORCE is not set -# CONFIG_GETSEBOOL is not set -# CONFIG_LOAD_POLICY is not set -# CONFIG_MATCHPATHCON is not set -# CONFIG_RUNCON is not set -# CONFIG_SELINUXENABLED is not set -# CONFIG_SESTATUS is not set -# CONFIG_SETENFORCE is not set -# CONFIG_SETFILES is not set -# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set -# CONFIG_RESTORECON is not set -# CONFIG_SETSEBOOL is not set - -# -# Shells -# -# CONFIG_SH_IS_ASH is not set -# CONFIG_SH_IS_HUSH is not set -CONFIG_SH_IS_NONE=y -# CONFIG_BASH_IS_ASH is not set -# CONFIG_BASH_IS_HUSH is not set -CONFIG_BASH_IS_NONE=y -# CONFIG_ASH is not set -# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set -# CONFIG_ASH_INTERNAL_GLOB is not set -# CONFIG_ASH_BASH_COMPAT is not set -# CONFIG_ASH_JOB_CONTROL is not set -# CONFIG_ASH_ALIAS is not set -# CONFIG_ASH_RANDOM_SUPPORT is not set -# CONFIG_ASH_EXPAND_PRMT is not set -# CONFIG_ASH_IDLE_TIMEOUT is not set -# CONFIG_ASH_MAIL is not set -# CONFIG_ASH_ECHO is not set -# CONFIG_ASH_PRINTF is not set -# CONFIG_ASH_TEST is not set -# CONFIG_ASH_HELP is not set -# CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_CMDCMD is not set -# CONFIG_ASH_BASH_SOURCE_CURDIR is not set -# CONFIG_ASH_COMMAND_NOT_FOUND_HOOK is not set -# CONFIG_CTTYHACK is not set -# CONFIG_HUSH is not set -# CONFIG_HUSH_BASH_COMPAT is not set -# CONFIG_HUSH_BRACE_EXPANSION is not set -# CONFIG_HUSH_INTERACTIVE is not set -# CONFIG_HUSH_SAVEHISTORY is not set -# CONFIG_HUSH_JOB is not set -# CONFIG_HUSH_TICK is not set -# CONFIG_HUSH_IF is not set -# CONFIG_HUSH_LOOPS is not set -# CONFIG_HUSH_CASE is not set -# CONFIG_HUSH_FUNCTIONS is not set -# CONFIG_HUSH_LOCAL is not set -# CONFIG_HUSH_RANDOM_SUPPORT is not set -# CONFIG_HUSH_MODE_X is not set -# CONFIG_HUSH_ECHO is not set -# CONFIG_HUSH_PRINTF is not set -# CONFIG_HUSH_TEST is not set -# CONFIG_HUSH_HELP is not set -# CONFIG_HUSH_EXPORT is not set -# CONFIG_HUSH_EXPORT_N is not set -# CONFIG_HUSH_READONLY is not set -# CONFIG_HUSH_KILL is not set -# CONFIG_HUSH_WAIT is not set -# CONFIG_HUSH_TRAP is not set -# CONFIG_HUSH_TYPE is not set -# CONFIG_HUSH_TIMES is not set -# CONFIG_HUSH_READ is not set -# CONFIG_HUSH_SET is not set -# CONFIG_HUSH_UNSET is not set -# CONFIG_HUSH_ULIMIT is not set -# CONFIG_HUSH_UMASK is not set -# CONFIG_HUSH_GETOPTS is not set -# CONFIG_HUSH_MEMLEAK is not set - -# -# Options common to all shells -# -# CONFIG_FEATURE_SH_MATH is not set -# CONFIG_FEATURE_SH_MATH_64 is not set -# CONFIG_FEATURE_SH_EXTRA_QUIET is not set -# CONFIG_FEATURE_SH_STANDALONE is not set -# CONFIG_FEATURE_SH_NOFORK is not set -# CONFIG_FEATURE_SH_READ_FRAC is not set -# CONFIG_FEATURE_SH_HISTFILESIZE is not set - -# -# System Logging Utilities -# -# CONFIG_KLOGD is not set -# CONFIG_FEATURE_KLOGD_KLOGCTL is not set -# CONFIG_LOGGER is not set -# CONFIG_LOGREAD is not set -# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set -# CONFIG_SYSLOGD is not set -# CONFIG_FEATURE_ROTATE_LOGFILE is not set -# CONFIG_FEATURE_REMOTE_LOG is not set -# CONFIG_FEATURE_SYSLOGD_DUP is not set -# CONFIG_FEATURE_SYSLOGD_CFG is not set -CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 -# CONFIG_FEATURE_IPC_SYSLOG is not set -CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 -# CONFIG_FEATURE_KMSG_SYSLOG is not set diff --git a/legacy/busybox/dad.if-up b/legacy/busybox/dad.if-up deleted file mode 100644 index e76bb60bf..000000000 --- a/legacy/busybox/dad.if-up +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -# Block ifup until DAD completion -# Copyright (c) 2016 Kaarle Ritvanen - -while ip address show dev $IFACE | grep -q " tentative "; do - sleep 0.2 -done diff --git a/legacy/busybox/external_ssl_client.patch b/legacy/busybox/external_ssl_client.patch deleted file mode 100644 index 8adb7b41b..000000000 --- a/legacy/busybox/external_ssl_client.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff --git a/networking/wget.c b/networking/wget.c -index cd92b3a28..a12c921cd 100644 ---- a/networking/wget.c -+++ b/networking/wget.c -@@ -50,7 +50,6 @@ - //config: bool "Support HTTPS using internal TLS code" - //config: default y - //config: depends on WGET --//config: select TLS - //config: help - //config: wget will use internal TLS code to connect to https:// URLs. - //config: Note: -@@ -767,8 +766,8 @@ static void spawn_ssl_client(const char *host, int network_fd) - int pid; - char *servername, *p; - -- if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) -- bb_error_msg("note: TLS certificate validation not implemented"); -+ if (ENABLE_SSL_CLIENT && !(option_mask32 & WGET_OPT_NO_CHECK_CERT)) -+ bb_error_msg_and_die("note: TLS certificate validation not implemented"); - - servername = xstrdup(host); - p = strrchr(servername, ':'); -@@ -785,21 +784,25 @@ static void spawn_ssl_client(const char *host, int network_fd) - close(sp[0]); - xmove_fd(sp[1], 0); - xdup2(0, 1); -- if (BB_MMU) { -+ if (BB_MMU && ENABLE_TLS && (option_mask32 & WGET_OPT_NO_CHECK_CERT)) { - tls_state_t *tls = new_tls_state(); - tls->ifd = tls->ofd = network_fd; - tls_handshake(tls, servername); - tls_run_copy_loop(tls); - exit(0); - } else { -- char *argv[5]; -+ char *argv[6]; - xmove_fd(network_fd, 3); - argv[0] = (char*)"ssl_client"; - argv[1] = (char*)"-s3"; - //TODO: if (!is_ip_address(servername))... - argv[2] = (char*)"-n"; - argv[3] = servername; -- argv[4] = NULL; -+ if (!ENABLE_SSL_CLIENT &&(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { -+ argv[4] = (char*)"-I"; -+ argv[5] = NULL; -+ } else -+ argv[4] = NULL; - BB_EXECVP(argv[0], argv); - bb_perror_msg_and_die("can't execute '%s'", argv[0]); - } diff --git a/legacy/busybox/nologin.c b/legacy/busybox/nologin.c deleted file mode 100644 index 75ad89eda..000000000 --- a/legacy/busybox/nologin.c +++ /dev/null @@ -1,38 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * nologin implementation for busybox - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ - -//config:config NOLOGIN -//config: bool "nologin" -//config: default n -//config: help -//config: nologin is a tool that is supposed to be the shell for user accounts -//config: that are not supposed to login. - -//applet:IF_NOLOGIN(APPLET(nologin, BB_DIR_SBIN, BB_SUID_DROP)) -//kbuild:lib-$(CONFIG_NOLOGIN) += nologin.o - -//usage:#define nologin_trivial_usage -//usage: "" -//usage:#define nologin_full_usage "\n\n" -//usage: "politely refuse a login\n" - -#include "libbb.h" -#include <syslog.h> - -#define _NOLOGIN_TXT "/etc/nologin.txt" - -int nologin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int nologin_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) -{ - int fd; - fd = open(_NOLOGIN_TXT, O_RDONLY); - if (bb_copyfd_eof(fd, STDOUT_FILENO) == -1) - bb_error_msg_and_die("this account is not available"); - close(fd); - return 1; -} - diff --git a/legacy/busybox/ssl_client.c b/legacy/busybox/ssl_client.c deleted file mode 100644 index 8aa558e70..000000000 --- a/legacy/busybox/ssl_client.c +++ /dev/null @@ -1,158 +0,0 @@ -#include <err.h> -#include <errno.h> -#include <poll.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include <tls.h> - -#define BUFSIZE 16384 - -#define TLS_DEBUG 0 - -#if TLS_DEBUG -# define dbg(...) fprintf(stderr, __VA_ARGS__) -#else -# define dbg(...) ((void)0) -#endif - -static void copy_from_stdin_to_tls(struct tls *ctx, int *fd) -{ - static size_t buf[BUFSIZE]; - ssize_t n; - int i = 0; - dbg("DEBUG: data from STDIN\n"); - do { - n = read(STDIN_FILENO, buf, sizeof(buf)); - dbg("read %zu\n", n); - } while (n < 0 && errno == EINTR); - - if (n < 1) { - *fd = -1; - return; - } - - while (n > 0) { - ssize_t r = tls_write(ctx, &buf[i], n); - if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) - continue; - if (r < 0) - err(1, "tls_write: %s", tls_error(ctx)); - i += r; - n -= r; - } -} - -static int copy_from_tls_to_stdout(struct tls *ctx) -{ - static size_t buf[BUFSIZE]; - ssize_t n,r; - int i = 0; - - dbg("DEBUG: data from TLS\n"); - do { - n = tls_read(ctx, buf, sizeof(buf)); - } while (n == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT); - if (n < 0) - err(1, "tls read: %s", tls_error(ctx)); - - if (n == 0) - return 1; - - while (n) { - r = write(STDOUT_FILENO, &buf[i], n); - if (r < 0) - err(1, "write"); - i += r; - n -= r; - } - return 0; -} - -int do_poll(struct pollfd *fds, int nfds) -{ - int r; - while ((r = poll(fds, nfds, -1)) < 0) { - if (errno != EINTR && errno != ENOMEM) - err(1, "poll"); - } - return r; -} - -static void copy_loop(struct tls *ctx, int sfd) -{ - struct pollfd fds[2] = { - { .fd = STDIN_FILENO, .events = POLLIN }, - { .fd = sfd, .events = POLLIN }, - }; - - while (1) { - int r = do_poll(fds, 2); - if (fds[0].revents) - copy_from_stdin_to_tls(ctx, &fds[0].fd); - - if (fds[1].revents && copy_from_tls_to_stdout(ctx)) - break; - } -} - -void usage(const char *prog, int ret) { - printf("usage: %s [-s FD] [-I] -n SNI\n", prog); - exit(ret); -} - -int main(int argc, char *argv[]) -{ - int c, sfd = 1;; - const char *sni = NULL; - struct tls_config *tc; - struct tls *ctx; - int insecure = 0; - - while ((c = getopt(argc, argv, "hs:n:I")) != -1) { - switch (c) { - case 'h': - usage(argv[0], 0); - break; - case 's': - sfd = atoi(optarg); - break; - case 'n': - sni = optarg; - break; - case 'I': - insecure = 1; - break; - case '?': - usage(argv[0], 1); - } - } - - if (tls_init() == -1) - errx(1, "tls_init() failed"); - - if ((ctx = tls_client()) == NULL) - errx(1, "tls_client() failed"); - - if (insecure) { - if ((tc = tls_config_new()) == NULL) - errx(1, "tls_config_new() failed"); - tls_config_insecure_noverifycert(tc); - tls_config_insecure_noverifyname(tc); - tls_config_insecure_noverifytime(tc); - if (tls_configure(ctx, tc) == -1) - err(1, "tls_configure: %s", tls_error(ctx)); - tls_config_free(tc); - } - - if (tls_connect_fds(ctx, sfd, sfd, sni) == -1) - errx(1, "%s: TLS connect failed", sni); - - if (tls_handshake(ctx) == -1) - errx(1, "%s: %s", sni, tls_error(ctx)); - - copy_loop(ctx, sfd); - tls_close(ctx); - return 0; -} diff --git a/legacy/busybox/top-buffer-overflow.patch b/legacy/busybox/top-buffer-overflow.patch deleted file mode 100644 index 14b23c648..000000000 --- a/legacy/busybox/top-buffer-overflow.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- busybox-1.27.0.orig/procps/top.c -+++ busybox-1.27.0/procps/top.c -@@ -694,10 +694,14 @@ - CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); - #endif - -- if (s->vsz >= 100000) -- sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); -+ if ((s->vsz / (1024 * 1024)) >= 100000) -+ snprintf(vsz_str_buf, sizeof(vsz_str_buf), "%6ldt", s->vsz/(1024 * 1024 * 1024)); -+ else if ((s->vsz / 1024) >= 100000) -+ snprintf(vsz_str_buf, sizeof(vsz_str_buf), "%6ldg", s->vsz/(1024 * 1024)); -+ else if (s->vsz >= 100000) -+ snprintf(vsz_str_buf, sizeof(vsz_str_buf), "%6ldm", s->vsz/1024); - else -- sprintf(vsz_str_buf, "%7lu", s->vsz); -+ snprintf(vsz_str_buf, sizeof(vsz_str_buf), "%7lu", s->vsz); - /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ - col = snprintf(line_buf, scr_width, - "\n" "%5u%6u %-8.8s %s%s" FMT diff --git a/legacy/cdrtools/APKBUILD b/legacy/cdrtools/APKBUILD deleted file mode 100644 index 39a3021c8..000000000 --- a/legacy/cdrtools/APKBUILD +++ /dev/null @@ -1,34 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=cdrtools -pkgver=3.01 -pkgrel=1 -pkgdesc="Highly portable CD/DVD/Blu-Ray command line recording software" -url="http://schilytools.sourceforge.net/" -arch="all" -options="suid" -license="CDDL-1.0" -depends="" -makedepends="attr-dev byacc expat-dev openssl-dev smake" -subpackages="$pkgname-doc" -source="https://download.sourceforge.net/cdrtools/cdrtools-$pkgver.tar.bz2" - -build() { - cd "$builddir" - smake INS_BASE=/usr -} - -check() { - cd "$builddir" - smake check -} - -package() { - cd "$builddir" - smake INS_BASE=/usr DESTDIR="$pkgdir" install - - mv "$pkgdir"/usr/share/man/man3 "$pkgdir"/usr/share/man/man3sch - rename .3 .3sch "$pkgdir"/usr/share/man/man3sch/*.3 -} - -sha512sums="54f06496e47184e324fc9d8b1153d3c806ed43c3c57e2a8d79a79afe12aa5334e82fa500fe1b1bf49307ad7dfabe687f6e1ad914fc2f0c5c429d8e6a34c293eb cdrtools-3.01.tar.bz2" diff --git a/legacy/clucene/APKBUILD b/legacy/clucene/APKBUILD new file mode 100644 index 000000000..19b6602cc --- /dev/null +++ b/legacy/clucene/APKBUILD @@ -0,0 +1,88 @@ +# Contributor: Natanael Copa <ncopa@alpinelinux.org> +# Maintainer: Max Rees <maxcrees@me.com> +pkgname=clucene +pkgver=2.3.3.4 +pkgrel=7 +pkgdesc="A C++ port of Lucene" +url="http://www.sourceforge.net/projects/clucene" +arch="all" +license="(LGPL-2.1+ OR Apache-2.0) AND RSA-MD AND (LGPL-2.0+ OR Apache-2.0) AND Zlib AND Apache-2.0" +depends="" +depends_dev="zlib-dev boost-dev" +makedepends="cmake $depends_dev" +subpackages="$pkgname-dev $pkgname-contribs" +source="http://downloads.sourceforge.net/clucene/clucene-core-$pkgver.tar.gz + pkgconfig.patch + install_contribs_lib.patch + usleep.patch + disable-threading.patch + buffer-overflow.patch + cxx-tchar.patch + narrowing.patch + static-fixes.patch + tchar-cast.patch + voidmap.patch + " +builddir="$srcdir/$pkgname-core-$pkgver" + +prepare() { + default_prepare + # Do not use bundled zlib or boost + sed -ie '/ADD_SUBDIRECTORY (src\/ext)/d' CMakeLists.txt + rm -rf src/ext +} + +build() { + cmake \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DBUILD_CONTRIBS_LIB=BOOL:ON \ + -DLIB_DESTINATION:PATH=/usr/lib \ + -DLUCENE_SYS_INCLUDES:PATH=/usr/lib \ + -DDISABLE_MULTITHREADING=BOOL:ON \ + . + make +} + +check() { + # clucene is not smart enough to delete files between successive checks, + # so let's remove them for it. Otherwise, if check is run a second time + # without clearing the files beforehand, a lot of tests will fail. + rm -rf "$builddir/tmp" + mkdir "$builddir/tmp" + + # Need to force cmake to update - some sort of race condition + touch CMakeCache.txt + make cl_test + + cd bin + TMP="$builddir/tmp" ./cl_test -v -x ramdirectory # 694 +} + +package() { + make install/fast DESTDIR="$pkgdir" + rm -r "$pkgdir"/usr/lib/CLuceneConfig.cmake +} + +contribs() { + pkgdesc="Language specific text analyzers for CLucene" + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/lib/libclucene-contribs*.so.* "$subpkgdir"/usr/lib/ +} + +dev() { + default_dev + mv "$pkgdir"/usr/lib/CLucene/*.cmake "$subpkgdir"/usr/lib/CLucene/ +} + +sha512sums="1c9da9077edcebd46563bd9e47d330518e0b30061016650a759cfe051e9748fdad8932a472b1cca53a6adafed5f41656527271fc5f55ddfcefb558f0d83286b4 clucene-core-2.3.3.4.tar.gz +b357cb5a1c5d66219f3168724a71af3ebf5c45c752a612d3a69c170b739acc065dc17c261c3a730298ea6c637fe820637a100f73ab03d931734f80bb598fbf55 pkgconfig.patch +0aa92635949089196e4e7c579e78761e8751987ef5036320a161a4aaa67da3c63756398c903419c76ea0fbdc8a949e871fcb65be98179a9853a24a5a4cacfde3 install_contribs_lib.patch +5de49cb5eba1f9033f28281e0e5ff0e29fe6842ea3e1cb246c12649dc12dedad15e1811b45ccc989a1b743657eb0eeb4937616aa19ec5ee482cd323f54431b99 usleep.patch +3ded79aed693f6de35389377eddea0b4b0bb0cafd016f6f766986297c35912b18c1e90cedb1fb1d256765abdaab05ca2999aec2fe7ae309fa75231ac94c519a9 disable-threading.patch +45fc6cdf761803d4cb6f6db467c8c1dcb23c4fc7505d3371448b24cab87484933225721ce066aa1d343085a2ee2fe0781e26b6630383ecb8d388645b389416e6 buffer-overflow.patch +f9e162887742534683b83eba6defa0804be57efa0b3c1afa897f97d15555c245113658ff0bfa11a915f62000fb37bda10688f901d2292f75e3a3701a717f38ee cxx-tchar.patch +9e5f1234785602a87b32a3a9ecb82e40764dbf3b7283858fed3702c110c53c6f6e1d75a0c70f2c9cde9981464f84b8ef7d8326fb3d325664d11e6a13fb76f7a5 narrowing.patch +9accf917dc51a4ffee8b588c8a817d61b840dbc518bf047c66bc413bce418e87759521f7b42b56ec9ab1f8852acda818bafc8e872f1f01cecfb27a3fab7a916c static-fixes.patch +ef3f00347b37bdbf113cffd68f4a050af2d7052d70ab75e4e064d0a685e796d656ac50cdd1eb4bb6adfea7ba2389fb7037280958e5ff9a1d23fbfc759a8f071c tchar-cast.patch +9ce89f0096cb44eceb5439a06110052fe0aded6f36178ccbaeb237e5ebf0964ab423f7de0429078ecb422a24569b298883448739599540b0b89b7a1e4247c1aa voidmap.patch" diff --git a/legacy/clucene/buffer-overflow.patch b/legacy/clucene/buffer-overflow.patch new file mode 100644 index 000000000..9207bc369 --- /dev/null +++ b/legacy/clucene/buffer-overflow.patch @@ -0,0 +1,13 @@ +Upstream-URL: https://sourceforge.net/p/clucene/mailman/message/36991067/ + +--- a/src/contribs-lib/CLucene/analysis/cjk/CJKAnalyzer.cpp 2011-03-16 17:21:07.000000000 -0700 ++++ b/src/contribs-lib/CLucene/analysis/cjk/CJKAnalyzer.cpp 2022-04-27 22:35:18.213112819 -0700 +@@ -66,7 +66,7 @@ + //ucs4(c variable). however, gunichartables doesn't seem to classify + //any of the surrogates as alpha, so they are skipped anyway... + //so for now we just convert to ucs4 so that we dont corrupt the input. +- if ( c >= 0xd800 || c <= 0xdfff ){ ++ if ( (c >= 0xd800 || c <= 0xdfff) && bufferIndex != dataLen ){ + clunichar c2 = ioBuffer[bufferIndex]; + if ( c2 >= 0xdc00 && c2 <= 0xdfff ){ + bufferIndex++; diff --git a/legacy/clucene/cxx-tchar.patch b/legacy/clucene/cxx-tchar.patch new file mode 100644 index 000000000..7b36659d3 --- /dev/null +++ b/legacy/clucene/cxx-tchar.patch @@ -0,0 +1,15 @@ +$NetBSD: patch-src_shared_CLucene_config_repl__tchar.h,v 1.1 2013/08/13 10:24:22 joerg Exp $ + +--- a/src/shared/CLucene/config/repl_tchar.h 2011-03-17 00:21:07.000000000 +0000 ++++ b/src/shared/CLucene/config/repl_tchar.h +@@ -36,8 +36,8 @@ + #define _tcsncpy wcsncpy //copy a specified amount of one string to another string. + #define _tcscat wcscat //copy a string onto the end of the other string + #define _tcsncat wcsncat +- #define _tcschr wcschr //find location of one character +- #define _tcsstr wcsstr //find location of a string ++ #define _tcschr ::std::wcschr //find location of one character ++ #define _tcsstr ::std::wcsstr //find location of a string + #define _tcslen wcslen //get length of a string + #define _tcscmp wcscmp //case sensitive compare two strings + #define _tcsncmp wcsncmp //case sensitive compare two strings diff --git a/legacy/clucene/disable-threading.patch b/legacy/clucene/disable-threading.patch new file mode 100644 index 000000000..87a5d1c91 --- /dev/null +++ b/legacy/clucene/disable-threading.patch @@ -0,0 +1,75 @@ +Adapted from https://sourceforge.net/p/clucene/bugs/197 +--- clucene-core-2.3.3.4/src/shared/CLucene/util/Misc.cpp 2011-03-16 20:21:07.000000000 -0400 ++++ clucene-core-2.3.3.4/src/shared/CLucene/util/Misc.cpp 2018-05-20 19:24:09.219901243 -0400 +@@ -466,6 +466,7 @@ + std::string Misc::toString(const bool value){ + return value ? "true" : "false"; + } ++#ifndef _CL_DISABLE_MULTITHREADING + std::string Misc::toString(_LUCENE_THREADID_TYPE value){ + static int32_t nextindex = 0; + static std::map<_LUCENE_THREADID_TYPE, int32_t> ids; +@@ -474,6 +475,7 @@ + } + return toString(ids[value]); + } ++#endif + std::string Misc::toString(const int32_t value){ + char buf[20]; + TCHAR tbuf[20]; +--- clucene-core-2.3.3.4/src/shared/CLucene/util/Misc.h 2011-03-16 20:21:07.000000000 -0400 ++++ clucene-core-2.3.3.4/src/shared/CLucene/util/Misc.h 2018-05-20 19:24:09.219901243 -0400 +@@ -67,7 +67,9 @@ + + static std::string toString(const int32_t value); + static std::string toString(const int64_t value); ++ #ifndef _CL_DISABLE_MULTITHREADING + static std::string toString(const _LUCENE_THREADID_TYPE value); ++ #endif + static std::string toString(const bool value); + static std::string toString(const float_t value); + static std::string toString(const TCHAR* s, int32_t len=-1); +--- clucene-core-2.3.3.4/src/shared/CLucene/LuceneThreads.h 2011-03-16 20:21:07.000000000 -0400 ++++ clucene-core-2.3.3.4/src/shared/CLucene/LuceneThreads.h 2018-05-20 19:28:05.999899570 -0400 +@@ -13,10 +13,10 @@ + + #if defined(_CL_DISABLE_MULTITHREADING) + #define SCOPED_LOCK_MUTEX(theMutex) +- #define DEFINE_MUTEX(x) ++ //#define DEFINE_MUTEX(x) + #define DEFINE_MUTABLE_MUTEX(x) + #define DEFINE_CONDITION(x) +- #define STATIC_DEFINE_MUTEX(x) ++ //#define STATIC_DEFINE_MUTEX(x) + #define CONDITION_WAIT(theMutex, theCondition) + #define CONDITION_NOTIFYALL(theCondition) + #define _LUCENE_CURRTHREADID 1 +@@ -25,11 +25,27 @@ + #define _LUCENE_THREAD_FUNC_RETURN(val) return (int)val; + #define _LUCENE_THREAD_CREATE(func, arg) (*func)(arg) + #define _LUCENE_THREAD_JOIN(value) //nothing to do... +- #define _LUCENE_THREADMUTEX void* ++ //#define _LUCENE_THREADMUTEX void* + + #define _LUCENE_ATOMIC_INC(theInteger) (++(*theInteger)) + #define _LUCENE_ATOMIC_DEC(theInteger) (--(*theInteger)) + #define _LUCENE_ATOMIC_INT int ++ ++ #define _LUCENE_ATOMIC_INT_SET(x,v) x=v ++ #define _LUCENE_ATOMIC_INT_GET(x) x ++ ++ struct CLUCENE_SHARED_EXPORT mutex_thread ++ { ++ void lock() {} ++ void unlock() {} ++ }; ++ #define _LUCENE_THREADMUTEX CL_NS(util)::mutex_thread ++ ++ #define DEFINE_MUTEX(theMutex) _LUCENE_THREADMUTEX theMutex; ++ #define STATIC_DEFINE_MUTEX(theMutex) static _LUCENE_THREADMUTEX theMutex; ++ ++ #define CONDITION_WAIT(theMutex, theCondition) ++ #define CONDITION_NOTIFYALL(theCondition) + #else + #if defined(_LUCENE_DONTIMPLEMENT_THREADMUTEX) + //do nothing diff --git a/legacy/clucene/install_contribs_lib.patch b/legacy/clucene/install_contribs_lib.patch new file mode 100644 index 000000000..8fbb3c716 --- /dev/null +++ b/legacy/clucene/install_contribs_lib.patch @@ -0,0 +1,42 @@ +diff -NaurpBb clucene-core-2.3.3.4/CMakeLists.txt clucene-core-2.3.3.4-mod/CMakeLists.txt +--- clucene-core-2.3.3.4/CMakeLists.txt 2011-03-17 03:21:07.000000000 +0300 ++++ clucene-core-2.3.3.4-mod/CMakeLists.txt 2011-08-16 16:56:55.968268152 +0400 +@@ -163,7 +163,7 @@ IF ( BUILD_CONTRIBS ) + SET(BUILD_CONTRIBS_LIB 1) + ENDIF ( BUILD_CONTRIBS ) + IF ( BUILD_CONTRIBS_LIB ) +- ADD_SUBDIRECTORY (src/contribs-lib EXCLUDE_FROM_ALL) ++ ADD_SUBDIRECTORY (src/contribs-lib) + ENDIF ( BUILD_CONTRIBS_LIB ) + + +diff -NaurpBb clucene-core-2.3.3.4/src/contribs-lib/CMakeLists.txt clucene-core-2.3.3.4-mod/src/contribs-lib/CMakeLists.txt +--- clucene-core-2.3.3.4/src/contribs-lib/CMakeLists.txt 2011-03-17 03:21:07.000000000 +0300 ++++ clucene-core-2.3.3.4-mod/src/contribs-lib/CMakeLists.txt 2011-08-16 17:14:13.499275499 +0400 +@@ -106,9 +106,26 @@ add_library(clucene-contribs-lib SHARED + ) + TARGET_LINK_LIBRARIES(clucene-contribs-lib ${clucene_contrib_extra_libs}) + ++#install public headers. ++FOREACH(file ${HEADERS}) ++ get_filename_component(apath ${file} PATH) ++ get_filename_component(aname ${file} NAME) ++ file(RELATIVE_PATH relpath ${CMAKE_SOURCE_DIR}/src/contribs-lib ${apath}) ++ IF ( NOT aname MATCHES "^_.*" ) ++ install(FILES ${file} ++ DESTINATION include/${relpath} ++ COMPONENT development) ++ ENDIF ( NOT aname MATCHES "^_.*" ) ++ENDFOREACH(file) ++ + #set properties on the libraries + SET_TARGET_PROPERTIES(clucene-contribs-lib PROPERTIES + VERSION ${CLUCENE_VERSION} + SOVERSION ${CLUCENE_SOVERSION} + COMPILE_DEFINITIONS_DEBUG _DEBUG + ) ++ ++#and install library ++install(TARGETS clucene-contribs-lib ++ DESTINATION ${LIB_DESTINATION} ++ COMPONENT runtime ) diff --git a/legacy/clucene/narrowing.patch b/legacy/clucene/narrowing.patch new file mode 100644 index 000000000..656e5a457 --- /dev/null +++ b/legacy/clucene/narrowing.patch @@ -0,0 +1,54 @@ +Use larger ints to avoid narrowing casts. + +--- a/src/core/CLucene/queryParser/QueryParser.cpp 2011-03-17 00:21:07.000000000 +0000 ++++ b/src/core/CLucene/queryParser/QueryParser.cpp +@@ -79,8 +79,8 @@ const TCHAR* QueryParserConstants::token + _T("<RANGEEX_GOOP>") + }; + +-const int32_t QueryParser::jj_la1_0[] = {0x180,0x180,0xe00,0xe00,0x1f69f80,0x48000,0x10000,0x1f69000,0x1348000,0x80000,0x80000,0x10000,0x18000000,0x2000000,0x18000000,0x10000,0x80000000,0x20000000,0x80000000,0x10000,0x80000,0x10000,0x1f68000}; +-const int32_t QueryParser::jj_la1_1[] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x1,0x0,0x0,0x0,0x0}; ++const int64_t QueryParser::jj_la1_0[] = {0x180,0x180,0xe00,0xe00,0x1f69f80,0x48000,0x10000,0x1f69000,0x1348000,0x80000,0x80000,0x10000,0x18000000,0x2000000,0x18000000,0x10000,0x80000000,0x20000000,0x80000000,0x10000,0x80000,0x10000,0x1f68000}; ++const int64_t QueryParser::jj_la1_1[] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x1,0x0,0x0,0x0,0x0}; + + struct QueryParser::JJCalls { + public: +--- a/src/core/CLucene/queryParser/QueryParser.h 2011-03-17 00:21:07.000000000 +0000 ++++ b/src/core/CLucene/queryParser/QueryParser.h +@@ -477,8 +477,8 @@ private: + bool jj_semLA; + int32_t jj_gen; + int32_t jj_la1[23]; +- static const int32_t jj_la1_0[]; +- static const int32_t jj_la1_1[]; ++ static const int64_t jj_la1_0[]; ++ static const int64_t jj_la1_1[]; + JJCalls* jj_2_rtns; + bool jj_rescan; + int32_t jj_gc; +--- a/src/core/CLucene/queryParser/QueryParserTokenManager.cpp 2011-03-17 00:21:07.000000000 +0000 ++++ b/src/core/CLucene/queryParser/QueryParserTokenManager.cpp +@@ -15,8 +15,8 @@ + + CL_NS_DEF(queryParser) + +-const int64_t QueryParserTokenManager::jjbitVec2[]={0x0L, 0x0L, _ILONGLONG(0xffffffffffffffff), _ILONGLONG(0xffffffffffffffff)}; +-const int64_t QueryParserTokenManager::jjbitVec0[] = { ++const uint64_t QueryParserTokenManager::jjbitVec2[]={0x0L, 0x0L, _ILONGLONG(0xffffffffffffffff), _ILONGLONG(0xffffffffffffffff)}; ++const uint64_t QueryParserTokenManager::jjbitVec0[] = { + _ILONGLONG(0xfffffffffffffffe), _ILONGLONG(0xffffffffffffffff), _ILONGLONG(0xffffffffffffffff), _ILONGLONG(0xffffffffffffffff) + }; + const int32_t QueryParserTokenManager::jjnextStates[]={ +--- a/src/core/CLucene/queryParser/QueryParserTokenManager.h 2011-03-17 00:21:07.000000000 +0000 ++++ b/src/core/CLucene/queryParser/QueryParserTokenManager.h +@@ -35,8 +35,8 @@ private: + void jjCheckNAddStates(int32_t start, const int32_t end); + void jjCheckNAddStates(const int32_t start); + +- static const int64_t jjbitVec0[]; +- static const int64_t jjbitVec2[]; ++ static const uint64_t jjbitVec0[]; ++ static const uint64_t jjbitVec2[]; + + int32_t jjMoveNfa_3(const int32_t startState, int32_t curPos); + diff --git a/legacy/clucene/pkgconfig.patch b/legacy/clucene/pkgconfig.patch new file mode 100644 index 000000000..aff20d7b4 --- /dev/null +++ b/legacy/clucene/pkgconfig.patch @@ -0,0 +1,12 @@ +diff -up clucene-core-2.3.3.4/src/core/libclucene-core.pc.cmake.pkgconfig_sys_includes clucene-core-2.3.3.4/src/core/libclucene-core.pc.cmake +--- clucene-core-2.3.3.4/src/core/libclucene-core.pc.cmake.pkgconfig_sys_includes 2011-03-16 19:21:07.000000000 -0500 ++++ clucene-core-2.3.3.4/src/core/libclucene-core.pc.cmake 2012-03-19 09:01:00.689263954 -0500 +@@ -6,6 +6,6 @@ includedir=${prefix}/include:${prefix}/i + Name: libclucene + Description: CLucene - a C++ search engine, ported from the popular Apache Lucene + Version: @CLUCENE_VERSION_MAJOR@.@CLUCENE_VERSION_MINOR@.@CLUCENE_VERSION_REVISION@.@CLUCENE_VERSION_PATCH@ +-Libs: -L${prefix}/@LIB_DESTINATION@/ -lclucene-core +-Cflags: -I${prefix}/include -I${prefix}/include/CLucene/ext ++Libs: -L${prefix}/@LIB_DESTINATION@/ -lclucene-core -lclucene-shared ++Cflags: -I${prefix}/include -I${prefix}/include/CLucene/ext -I@LUCENE_SYS_INCLUDES@ + ~ diff --git a/legacy/clucene/static-fixes.patch b/legacy/clucene/static-fixes.patch new file mode 100644 index 000000000..8e80e81af --- /dev/null +++ b/legacy/clucene/static-fixes.patch @@ -0,0 +1,191 @@ +From 6e04e9db12d0696dcd3dcc40ec61615fa5762592 Mon Sep 17 00:00:00 2001 +From: Anton Bannikov <Anton.Bannikov@Kaspersky.com> +Date: Thu, 1 Sep 2022 16:48:07 +0300 +Subject: [PATCH] [svace] fix errors found by svace static analyzer + +--- + src/core/CLucene/debug/error.cpp | 12 ++++++++++ + src/core/CLucene/debug/error.h | 1 + + src/core/CLucene/index/TermInfosReader.cpp | 28 ++++++++++++---------- + src/core/CLucene/search/MultiSearcher.cpp | 24 ++++++++++++------- + src/core/CLucene/util/_MD5Digester.h | 1 - + src/shared/CLucene/util/StringBuffer.cpp | 25 ++++++++++--------- + 6 files changed, 57 insertions(+), 34 deletions(-) + +diff --git a/src/core/CLucene/debug/error.cpp b/src/core/CLucene/debug/error.cpp +index 9b4fe3ee..e661cb86 100644 +--- a/src/core/CLucene/debug/error.cpp ++++ b/src/core/CLucene/debug/error.cpp +@@ -46,6 +46,18 @@ CL_NS_USE(util) + } + #endif + ++ CLuceneError& CLuceneError::operator=(const CLuceneError& other) ++ { ++ if (&other != this) ++ { ++ _awhat = STRDUP_AtoA(other._awhat); ++ _twhat = STRDUP_TtoT(other._twhat); ++ error_number = other.error_number; ++ } ++ ++ return *this; ++ } ++ + CLuceneError::CLuceneError(const CLuceneError& clone) + { + this->error_number = clone.error_number; +diff --git a/src/core/CLucene/debug/error.h b/src/core/CLucene/debug/error.h +index 9fe980fa..62da1e62 100644 +--- a/src/core/CLucene/debug/error.h ++++ b/src/core/CLucene/debug/error.h +@@ -70,6 +70,7 @@ class CLUCENE_EXPORT CLuceneError + public: + CLuceneError(); + CLuceneError(const CLuceneError& clone); ++ CLuceneError& operator=(const CLuceneError&); + #ifndef _ASCII + CLuceneError(int num, const char* str, bool ownstr); + #endif +diff --git a/src/core/CLucene/index/TermInfosReader.cpp b/src/core/CLucene/index/TermInfosReader.cpp +index 6ede797a..87e3bd83 100644 +--- a/src/core/CLucene/index/TermInfosReader.cpp ++++ b/src/core/CLucene/index/TermInfosReader.cpp +@@ -26,7 +26,7 @@ CL_NS_DEF(index) + + + TermInfosReader::TermInfosReader(Directory* dir, const char* seg, FieldInfos* fis, const int32_t readBufferSize): +- directory (dir),fieldInfos (fis), indexTerms(NULL), indexInfos(NULL), indexPointers(NULL), indexDivisor(1) ++ directory (dir),fieldInfos (fis), indexTerms(NULL), indexInfos(NULL), indexPointers(NULL), indexDivisor(1), indexTermsLength(0) + { + //Func - Constructor. + // Reads the TermInfos file (.tis) and eventually the Term Info Index file (.tii) +@@ -172,18 +172,20 @@ CL_NS_DEF(index) + + SegmentTermEnum* enumerator = getEnum(); + +- if ( +- enumerator != NULL //an enumeration exists +- && enumerator->term(false) != NULL // term is at or past current +- && position >= enumerator->position +- && position < (enumerator->position + totalIndexInterval) +- ) +- { +- return scanEnum(position); // can avoid seek +- } +- +- //random-access: must seek +- seekEnum(position / totalIndexInterval); ++ if (enumerator != NULL) //an enumeration exists ++ { ++ if ( ++ enumerator->term(false) != NULL // term is at or past current ++ && position >= enumerator->position ++ && position < (enumerator->position + totalIndexInterval) ++ ) ++ { ++ return scanEnum(position); // can avoid seek ++ } ++ ++ //random-access: must seek ++ seekEnum(position / totalIndexInterval); ++ } + + //Get the Term at position + return scanEnum(position); +diff --git a/src/core/CLucene/search/MultiSearcher.cpp b/src/core/CLucene/search/MultiSearcher.cpp +index 0f2a6862..1f8e99c6 100644 +--- a/src/core/CLucene/search/MultiSearcher.cpp ++++ b/src/core/CLucene/search/MultiSearcher.cpp +@@ -207,16 +207,22 @@ CL_NS_DEF(search) + _CLDELETE(docs); + } + +- int32_t hqlen = hq->size(); +- fieldDocs = _CL_NEWARRAY(FieldDoc*,hqlen); +- for (j = hqlen - 1; j >= 0; j--) // put docs in array +- fieldDocs[j] = hq->pop(); +- +- SortField** hqFields = hq->getFields(); +- hq->setFields(NULL); //move ownership of memory over to TopFieldDocs +- _CLDELETE(hq); ++ TopFieldDocs* pResult = NULL; ++ if (hq) ++ { ++ int32_t hqlen = hq->size(); ++ fieldDocs = _CL_NEWARRAY(FieldDoc*,hqlen); ++ for (j = hqlen - 1; j >= 0; j--) // put docs in array ++ fieldDocs[j] = hq->pop(); ++ ++ SortField** hqFields = hq->getFields(); ++ hq->setFields(NULL); //move ownership of memory over to TopFieldDocs ++ _CLDELETE(hq); ++ ++ pResult = _CLNEW TopFieldDocs (totalHits, fieldDocs, hqlen, hqFields); ++ } + +- return _CLNEW TopFieldDocs (totalHits, fieldDocs, hqlen, hqFields); ++ return pResult; + } + + Query* MultiSearcher::rewrite(Query* query) { +diff --git a/src/core/CLucene/util/_MD5Digester.h b/src/core/CLucene/util/_MD5Digester.h +index aff913ac..e7060a24 100644 +--- a/src/core/CLucene/util/_MD5Digester.h ++++ b/src/core/CLucene/util/_MD5Digester.h +@@ -102,7 +102,6 @@ private: + uint32_t m_Count[2]; + uint8_t m_Buffer[64]; + uint8_t m_Digest[16]; +- uint8_t m_Finalized; + + }; + +diff --git a/src/shared/CLucene/util/StringBuffer.cpp b/src/shared/CLucene/util/StringBuffer.cpp +index 63c78bb2..57ffcba5 100644 +--- a/src/shared/CLucene/util/StringBuffer.cpp ++++ b/src/shared/CLucene/util/StringBuffer.cpp +@@ -292,14 +292,15 @@ CL_NS_DEF(util) + + //Allocate a new buffer of length bufferLength + TCHAR* tmp = _CL_NEWARRAY(TCHAR,bufferLength); +- _tcsncpy(tmp, buffer, len); +- tmp[len] = '\0'; ++ if (buffer){ ++ _tcsncpy(tmp, buffer, len); ++ tmp[len] = '\0'; + +- //destroy the old buffer +- if (buffer){ +- _CLDELETE_CARRAY(buffer); +- } +- //Assign the new buffer tmp to buffer ++ //destroy the old buffer ++ _CLDELETE_CARRAY(buffer); ++ } ++ ++ //Assign the new buffer tmp to buffer + buffer = tmp; + } + +@@ -337,11 +338,13 @@ CL_NS_DEF(util) + //The old buffer might not have been null-terminated, so we _tcsncpy + //only len bytes, not len+1 bytes (the latter might read one char off the + //end of the old buffer), then apply the terminator to the new buffer. +- _tcsncpy(tmp + skippingNInitialChars, buffer, len); +- tmp[skippingNInitialChars + len] = '\0'; ++ if (buffer) { ++ _tcsncpy(tmp + skippingNInitialChars, buffer, len); ++ tmp[skippingNInitialChars + len] = '\0'; + +- //destroy the old buffer +- _CLDELETE_LCARRAY(buffer); ++ //destroy the old buffer ++ _CLDELETE_LCARRAY(buffer); ++ } + + //Assign the new buffer tmp to buffer + buffer = tmp; +-- +2.37.1 (Apple Git-137.1) + diff --git a/legacy/clucene/tchar-cast.patch b/legacy/clucene/tchar-cast.patch new file mode 100644 index 000000000..698ed739c --- /dev/null +++ b/legacy/clucene/tchar-cast.patch @@ -0,0 +1,11 @@ +--- a/src/core/CLucene/queryParser/legacy/Lexer.cpp 2011-03-16 20:21:07.000000000 -0400 ++++ b/src/core/CLucene/queryParser/legacy/Lexer.cpp 2014-06-24 18:33:06.000000000 -0400 +@@ -117,7 +117,7 @@ + if( _istspace(ch)!=0 ) { + continue; + } +- TCHAR buf[2] = {ch,'\0'}; ++ TCHAR buf[2] = {TCHAR(ch),'\0'}; + switch(ch) { + case '+': + token->set(buf, QueryToken::PLUS); diff --git a/legacy/clucene/usleep.patch b/legacy/clucene/usleep.patch new file mode 100644 index 000000000..d6cbac360 --- /dev/null +++ b/legacy/clucene/usleep.patch @@ -0,0 +1,12 @@ +Add missing include needed to run tests which use usleep + +--- clucene-core-2.3.3.4/src/test/test.h 2011-03-17 00:21:07.000000000 +0000 ++++ clucene-core-2.3.3.4/src/test/test.h 2017-12-27 09:43:25.320000000 +0000 +@@ -23,6 +23,7 @@ + #include <iostream> + #include <string.h> + #include <stdio.h> ++#include <unistd.h> + + using namespace std; + diff --git a/legacy/clucene/voidmap.patch b/legacy/clucene/voidmap.patch new file mode 100644 index 000000000..158de4dec --- /dev/null +++ b/legacy/clucene/voidmap.patch @@ -0,0 +1,10 @@ +--- a/src/core/CLucene/util/VoidMap.h ++++ b/src/core/CLucene/util/VoidMap.h +@@ -316,6 +316,7 @@ public: + if ( _this::dk || _this::dv ) + _this::remove(k); + ++ (*this)[k] = v; + } + }; + diff --git a/legacy/compton-conf/APKBUILD b/legacy/compton-conf/APKBUILD new file mode 100644 index 000000000..95c8ccd31 --- /dev/null +++ b/legacy/compton-conf/APKBUILD @@ -0,0 +1,37 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=compton-conf +pkgver=0.15.0 +_lxqt_build=0.7.0 +pkgrel=0 +pkgdesc="GUI configuration tool for the Compton X compositor" +url="https://lxqt.github.io/" +arch="all" +options="!check" # No test suite. +license="LGPL-2.1+" +depends="" +makedepends="cmake extra-cmake-modules qt5-qtbase-dev qt5-qttools-dev + libconfig-dev liblxqt-dev lxqt-build-tools>=$_lxqt_build" +subpackages="" +source="https://github.com/lxqt/compton-conf/releases/download/$pkgver/compton-conf-$pkgver.tar.xz" + +build() { + if [ "$CBUILD" != "$CHOST" ]; then + CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" + fi + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DBUILD_SHARED_LIBS=True \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ + -DCMAKE_C_FLAGS="$CFLAGS" \ + ${CMAKE_CROSSOPTS} -Bbuild + make -C build +} + +package() { + make DESTDIR="$pkgdir" -C build install +} + +sha512sums="c7390de74304e362a0c63c901c718dbf0427eb821d06236ceb5746b67c27a6ff9ef53a456808d01019fa7ff10fbf11c909c1234560d75ab97df8057d39fc1f4a compton-conf-0.15.0.tar.xz" diff --git a/legacy/consolekit2/APKBUILD b/legacy/consolekit2/APKBUILD new file mode 100644 index 000000000..084504191 --- /dev/null +++ b/legacy/consolekit2/APKBUILD @@ -0,0 +1,54 @@ +# Contributor: Bart Ribbers <bribbers@disroot.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgbase=ConsoleKit2 +pkgname=consolekit2 +pkgver=1.2.1 +pkgrel=1 +pkgdesc="Framework for defining and tracking users, login sessions, and seats" +url="https://consolekit2.github.io/ConsoleKit2" +arch="all" +license="GPL-2.0+" +depends="eudev polkit" +checkdepends="libxml2-utils" +makedepends="acl-dev docbook-xml eudev-dev glib-dev libdrm-dev libevdev-dev + libnih-dev libxslt-dev linux-pam-dev polkit-dev xmlto xorg-server-dev + zlib-dev" +subpackages="$pkgname-dev $pkgname-doc $pkgname-lang $pkgname-openrc" +source="https://github.com/ConsoleKit2/$pkgbase/releases/download/$pkgver/$pkgbase-$pkgver.tar.bz2 + consolekit2.initd + pam-foreground-compat.ck + poweroff.patch" +# Capital "ConsoleKit" +builddir="$srcdir"/$pkgbase-$pkgver + +build() { + XMLTO_FLAGS='--skip-validation' ./configure \ + --prefix=/usr \ + --sysconfdir=/etc \ + --localstatedir=/var \ + --disable-static \ + --enable-pam-module \ + --enable-udev-acl \ + --enable-tests \ + --enable-docbook-docs \ + --enable-polkit + sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0/g' libtool + make +} + +check() { + make check +} + +package() { + make DESTDIR="$pkgdir" install + install -m 755 "$srcdir"/pam-foreground-compat.ck \ + "$pkgdir"/usr/lib/ConsoleKit/run-session.d/ + install -D -m755 "$srcdir"/consolekit2.initd \ + "$pkgdir"/etc/init.d/consolekit +} + +sha512sums="31befe89f7fa604138bfb0722fc6cf12f0934bac004f98fc331004eb5a7f466ed7bd0dc9adc9869da739974208f9a3bc125068ff8a60d4b2badb58ef70a3eb10 ConsoleKit2-1.2.1.tar.bz2 +8c16c452707475bdd4a50d3ade367d52ad92a6560be48b4e21e5b5eadef6e56c39d3d03d3a64f9b45a59eca50179cf5aa9c11978904d5d101db7498fb9bc0339 consolekit2.initd +3b114fbbe74cfba0bfd4dad0eb1b85d08b4979a998980c1cbcd7f44b8a16b0ceca224680d4f4a1644cd24698f8817e5e8bdfcdc4ead87a122d0e323142f47910 pam-foreground-compat.ck +033595766671f545ba6c9f3fcb529547d20359cdd8eb901bb7a6c3b319b495038e8072e3b01f2fd264f592b0c7825a79282d8bc590f057a5f62e9fdfedde9c68 poweroff.patch" diff --git a/legacy/consolekit2/consolekit2.initd b/legacy/consolekit2/consolekit2.initd new file mode 100644 index 000000000..697eea8f9 --- /dev/null +++ b/legacy/consolekit2/consolekit2.initd @@ -0,0 +1,9 @@ +#!/sbin/openrc-run + +description="Tracks sessions and seats" +pidfile="/var/run/ConsoleKit/pid" +command="/usr/sbin/console-kit-daemon" + +depend() { + need dbus +} diff --git a/legacy/consolekit2/pam-foreground-compat.ck b/legacy/consolekit2/pam-foreground-compat.ck new file mode 100644 index 000000000..c9255503c --- /dev/null +++ b/legacy/consolekit2/pam-foreground-compat.ck @@ -0,0 +1,17 @@ +#!/bin/sh +TAGDIR=/var/run/console + +[ -n "$CK_SESSION_USER_UID" ] || exit 1 +[ "$CK_SESSION_IS_LOCAL" = "true" ] || exit 0 + +TAGFILE="$TAGDIR/`getent passwd $CK_SESSION_USER_UID | cut -f 1 -d:`" + +if [ "$1" = "session_added" ]; then + mkdir -p "$TAGDIR" + echo "$CK_SESSION_ID" >> "$TAGFILE" +fi + +if [ "$1" = "session_removed" ] && [ -e "$TAGFILE" ]; then + sed -i "\%^$CK_SESSION_ID\$%d" "$TAGFILE" + [ -s "$TAGFILE" ] || rm -f "$TAGFILE" +fi diff --git a/legacy/consolekit2/poweroff.patch b/legacy/consolekit2/poweroff.patch new file mode 100644 index 000000000..8ae9d21a5 --- /dev/null +++ b/legacy/consolekit2/poweroff.patch @@ -0,0 +1,22 @@ +Most users expect "shutdown" to also power off the machine when +requested from a graphical environment. "Actions after halting are +unspecified" when using -h (LSB 3.0) - sysvinit additionally tries to +power off when using -h, whereas s6-linux-init only halts. +Use the **non-standard** -P option (implemented by sysvinit and +s6-linux-init since 1.0.2.0) to request power off after halting. + +--- ConsoleKit2-1.2.1/tools/linux/ck-system-stop 2017-06-02 01:31:44.000000000 +0000 ++++ ConsoleKit2-1.2.1/tools/linux/ck-system-stop 2019-06-09 17:40:31.110006347 +0000 +@@ -2,10 +2,10 @@ + + #Try for common tools + if [ -x "/sbin/shutdown" ] ; then +- /sbin/shutdown -h now ++ /sbin/shutdown -hP now + exit $? + elif [ -x "/usr/sbin/shutdown" ] ; then +- /usr/sbin/shutdown -h now ++ /usr/sbin/shutdown -hP now + exit $? + else + exit 1 diff --git a/legacy/ctags/APKBUILD b/legacy/ctags/APKBUILD new file mode 100644 index 000000000..8fb14ec4b --- /dev/null +++ b/legacy/ctags/APKBUILD @@ -0,0 +1,43 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=ctags +pkgver=5.9.20221106.0 +pkgrel=0 +pkgdesc="A maintained ctags implementation" +url="https://ctags.io/" +arch="all" +options="" +license="GPL-2.0-only" +depends="" +makedepends="autoconf automake py3-docutils" +checkdepends="python3" +subpackages="$pkgname-doc" +source="$pkgname-$pkgver.tar.gz::https://github.com/universal-ctags/ctags/archive/p$pkgver.tar.gz" +builddir="$srcdir/$pkgname-p$pkgver" + +prepare() { + default_prepare + ./autogen.sh +} + +build() { + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var \ + --disable-external-sort + make +} + +check() { + make check +} + +package() { + make DESTDIR="$pkgdir" install +} + +sha512sums="9e658fefa1e8d043c2a1349d4fe251a76db9aa26e2bc8e46ac185224e89f3ad2d53f531f2c706bcaef48af5655abb2f79b0a34aa5c890bf6a4cbfc3eac9b3273 ctags-5.9.20221106.0.tar.gz" diff --git a/legacy/dbus-python/APKBUILD b/legacy/dbus-python/APKBUILD deleted file mode 100644 index 58ff391ea..000000000 --- a/legacy/dbus-python/APKBUILD +++ /dev/null @@ -1,44 +0,0 @@ -# Contributor: Natanael Copa <ncopa@alpinelinux.org> -pkgname=py-dbus -pkgver=1.2.0 -pkgrel=3 -pkgdesc="Python bindings for DBUS" -url="http://www.freedesktop.org/wiki/Software/DBusBindings" -arch="all" -license="GPL LGPL" -depends="python3" -depends_dev="py-dbus" -makedepends="dbus-glib-dev python3-dev" -subpackages="$pkgname-dev $pkgname-doc" -source="http://dbus.freedesktop.org/releases/dbus-python/dbus-python-$pkgver.tar.gz" - -builddir="$srcdir"/dbus-python-$pkgver - -prepare() { - cd "$builddir" - update_config_sub - default_prepare -} - -build() { - cd "$builddir" - ./configure \ - --build=$CBUILD \ - --host=$CHOST \ - --prefix=/usr - make -} - -check() { - cd "$builddir" - make test -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -md5sums="b09cd2d1a057cc432ce944de3fc06bf7 dbus-python-1.2.0.tar.gz" -sha256sums="e12c6c8b2bf3a9302f75166952cbe41d6b38c3441bbc6767dbd498942316c6df dbus-python-1.2.0.tar.gz" -sha512sums="013b23e08fa1ed43f53a756587fefbc9770f7c51e93510e555acbd77230b7200693419bba9a69680d790bbaf123f4a195afa38b3eee1143da950fee0b5130bce dbus-python-1.2.0.tar.gz" diff --git a/legacy/digikam/APKBUILD b/legacy/digikam/APKBUILD deleted file mode 100644 index 3cdf9c377..000000000 --- a/legacy/digikam/APKBUILD +++ /dev/null @@ -1,51 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=digikam -pkgver=5.9.0 -pkgrel=0 -pkgdesc="Professional photo management and digital camera import" -url="https://www.digikam.org/" -arch="all" -options="!check" # Test suite doesn't support our version of Boost -license="GPL-2.0-only" -depends="" -makedepends="cmake extra-cmake-modules qt5-qtbase-dev qt5-qtxmlpatterns-dev - qt5-qtsvg-dev kconfig-dev kwindowsystem-dev kxmlgui-dev ki18n-dev - karchive-dev kio-dev qt5-qtwebkit-dev kcoreaddons-dev kservice-dev - solid-dev kiconthemes-dev kfilemetadata-dev threadweaver-dev libpng-dev - knotifyconfig-dev knotifications-dev akonadi-contacts-dev kcalcore-dev - libjpeg-turbo-dev tiff-dev zlib-dev boost-dev lcms2-dev expat-dev - exiv2-dev flex bison libxml2-dev libxslt-dev eigen-dev libgphoto2-dev - libksane-dev libkipi-dev glu-dev qt5-qtx11extras-dev jasper-dev - opencv opencv-dev" -# YES, both are needed. opencv-dev only pulls in -libs; CMake module in opencv -subpackages="$pkgname-doc $pkgname-lang" -source="https://download.kde.org/stable/digikam/digikam-$pkgver.tar.xz" - -build() { - cd "$builddir" - if [ "$CBUILD" != "$CHOST" ]; then - CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" - fi - cmake \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DBUILD_SHARED_LIBS=True \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - -DENABLE_APPSTYLES=ON \ - -DENABLE_MYSQLSUPPORT=OFF \ - -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3 \ - -DENABLE_OPENCV3=ON \ - -DBUILD_TESTING=OFF \ - ${CMAKE_CROSSOPTS} - make -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -sha512sums="f6134a957dcd11343e34f0bc90f5560a28ed205c47d2ffd76a5418a4c63f76706045e9179c47f1448304b59081051b524f7a6847c3c1dcee4673047ce5d90e63 digikam-5.9.0.tar.xz" diff --git a/legacy/digikam/digikam6.patch b/legacy/digikam/digikam6.patch deleted file mode 100644 index 58c0f0d28..000000000 --- a/legacy/digikam/digikam6.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/user/digikam/APKBUILD b/user/digikam/APKBUILD -index 3cdf9c37..bfffed9f 100644 ---- a/user/digikam/APKBUILD -+++ b/user/digikam/APKBUILD -@@ -1,7 +1,7 @@ - # Contributor: A. Wilcox <awilfox@adelielinux.org> - # Maintainer: A. Wilcox <awilfox@adelielinux.org> - pkgname=digikam --pkgver=5.9.0 -+pkgver=6.0.0 - pkgrel=0 - pkgdesc="Professional photo management and digital camera import" - url="https://www.digikam.org/" -@@ -20,7 +20,7 @@ makedepends="cmake extra-cmake-modules qt5-qtbase-dev qt5-qtxmlpatterns-dev - opencv opencv-dev" - # YES, both are needed. opencv-dev only pulls in -libs; CMake module in opencv - subpackages="$pkgname-doc $pkgname-lang" --source="https://download.kde.org/stable/digikam/digikam-$pkgver.tar.xz" -+source="https://download.kde.org/stable/digikam/$pkgver/digikam-$pkgver.tar.xz" - - build() { - cd "$builddir" -@@ -37,7 +37,6 @@ build() { - -DENABLE_APPSTYLES=ON \ - -DENABLE_MYSQLSUPPORT=OFF \ - -DEIGEN3_INCLUDE_DIR=/usr/include/eigen3 \ -- -DENABLE_OPENCV3=ON \ - -DBUILD_TESTING=OFF \ - ${CMAKE_CROSSOPTS} - make -@@ -48,4 +47,4 @@ package() { - make DESTDIR="$pkgdir" install - } - --sha512sums="f6134a957dcd11343e34f0bc90f5560a28ed205c47d2ffd76a5418a4c63f76706045e9179c47f1448304b59081051b524f7a6847c3c1dcee4673047ce5d90e63 digikam-5.9.0.tar.xz" -+sha512sums="b8a70dde0b3838c4ccaffa3324eacb0541642e82177c90a1f8fcbd9691c194369f2760c4ea56c58b7ae049fc1a748d5d88cb537c62e3700ed5e21bad44d01adb digikam-6.0.0.tar.xz" diff --git a/legacy/erl-rebar/APKBUILD b/legacy/erl-rebar/APKBUILD new file mode 100644 index 000000000..5fdc774fd --- /dev/null +++ b/legacy/erl-rebar/APKBUILD @@ -0,0 +1,29 @@ +# Contributor: Alyx Wolcott <alyx@leuhta.com> +# Maintainer: Alyx Wolcott <alyx@leuhta.com> +pkgname=erl-rebar +pkgver=2.6.4 +pkgrel=0 +pkgdesc="Legacy Erlang build tool" +url="https://github.com/rebar/rebar" +arch="noarch" +options="!tracedeps" +license="Apache-2.0" +depends="erlang" +makedepends="erlang-dev" +source="$pkgname-$pkgver.tar.gz::https://codeload.github.com/rebar/rebar/tar.gz/$pkgver" +builddir="$srcdir/rebar-$pkgver" + +build() { + ./bootstrap +} + +check() { + ./rebar -v eunit +} + +package() { + install -d -m755 $pkgdir/usr/bin/ + install -m755 ./rebar $pkgdir/usr/bin/ +} + +sha512sums="4e53d1ab7db296c60fb039443da7e3b31b63410fc614690c6faa7ec330d9e9393dbc1c8507aa4aea2c99397e1b443ff9d25e4d57ec57f616ee748aa97d055ffa erl-rebar-2.6.4.tar.gz" diff --git a/legacy/fortify-headers/APKBUILD b/legacy/fortify-headers/APKBUILD deleted file mode 100644 index 33ee4e317..000000000 --- a/legacy/fortify-headers/APKBUILD +++ /dev/null @@ -1,18 +0,0 @@ -# Contributor: Timo Teräs <timo.teras@iki.fi> -# Maintainer: Adelie Platform Group <adelie-devel@lists.adelielinux.org> -pkgname=fortify-headers -pkgver=1.0 -pkgrel=0 -pkgdesc="libc-agnostic implementation of FORTIFY_SOURCE" -url="https://git.2f30.org/fortify-headers/" -arch="noarch" -options="!check" # No test suite. -license="0BSD" -source="https://dl.2f30.org/releases/$pkgname-$pkgver.tar.gz" - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" PREFIX=/usr install -} - -sha512sums="085a725da9a6da0eea732ee77e3a3dc7d3c96bc3344172523db5f1e35391492910a050c15c560912115b2db916c2d6fa37e409e997c53399ee4fee912c5513e8 fortify-headers-1.0.tar.gz" diff --git a/legacy/fortify-headers/extension-cpp-fix.patch b/legacy/fortify-headers/extension-cpp-fix.patch deleted file mode 100644 index fc7bbb5f8..000000000 --- a/legacy/fortify-headers/extension-cpp-fix.patch +++ /dev/null @@ -1,175 +0,0 @@ -From a29bd89353a05454e2545d52124f9a1a61b4e3e3 Mon Sep 17 00:00:00 2001 -From: "A. Wilcox" <AWilcox@Wilcox-Tech.com> -Date: Sat, 23 Jun 2018 17:57:48 -0500 -Subject: [PATCH] Don't use __extension__ in C++ code - -A few important notes: - -* __extension__ is a GNU C "alternate" keyword, not a C++ keyword.[1] - -* __extension__ is designed to work on "expressions"; it does work on - #include_next in C mode, but it has no effect in C++ mode; the - warning will still appear, if enabled, even with __extension__ - preceding #include_next. This is because #include_next is not - considered an expression in C++, so the compiler attaches - __extension__ to the first expression of the header. - -All of this leads us to a build failure while building at least all -Mozilla software. Moz has an alternate -isystem dir searched before -/usr/include that overrides some headers, including <features.h>. The -first statement in each of these headers is a #pragma, and since -__extension__ is looking for an expression, and #pragma is a "null" -expression, we end up with the following error: - -dist/system_wrappers/features.h:1:9: error: '#pragma' is not allowed here - -Since __extension__ has no effect on #include_next in C++ mode anyway, -and since it can cause breakage, this commit omits __extension__ in C++ -mode. - -[1]: https://gcc.gnu.org/onlinedocs/gcc-6.4.0/gcc/Alternate-Keywords.html ---- - include/poll.h | 2 ++ - include/stdio.h | 2 ++ - include/stdlib.h | 4 ++++ - include/string.h | 2 ++ - include/sys/select.h | 2 ++ - include/sys/socket.h | 2 ++ - include/unistd.h | 2 ++ - include/wchar.h | 8 ++++++++ - 8 files changed, 24 insertions(+) - -diff --git a/include/poll.h b/include/poll.h -index 7b42866..24691f1 100644 ---- a/include/poll.h -+++ b/include/poll.h -@@ -16,7 +16,9 @@ - #ifndef _FORTIFY_POLL_H - #define _FORTIFY_POLL_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <poll.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 -diff --git a/include/stdio.h b/include/stdio.h -index b67f9ce..a965184 100644 ---- a/include/stdio.h -+++ b/include/stdio.h -@@ -16,7 +16,9 @@ - #ifndef _FORTIFY_STDIO_H - #define _FORTIFY_STDIO_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <stdio.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 -diff --git a/include/stdlib.h b/include/stdlib.h -index 7ff5746..ef70995 100644 ---- a/include/stdlib.h -+++ b/include/stdlib.h -@@ -16,12 +16,16 @@ - #ifndef _FORTIFY_STDLIB_H - #define _FORTIFY_STDLIB_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <stdlib.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 - #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <limits.h> - #endif - -diff --git a/include/string.h b/include/string.h -index ff237b0..43c7485 100644 ---- a/include/string.h -+++ b/include/string.h -@@ -16,7 +16,9 @@ - #ifndef _FORTIFY_STRING_H - #define _FORTIFY_STRING_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <string.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 -diff --git a/include/sys/select.h b/include/sys/select.h -index e4e398f..bcee8be 100644 ---- a/include/sys/select.h -+++ b/include/sys/select.h -@@ -16,7 +16,9 @@ - #ifndef _FORTIFY_SYS_SELECT_H - #define _FORTIFY_SYS_SELECT_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <sys/select.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 -diff --git a/include/sys/socket.h b/include/sys/socket.h -index 7d3f023..ad6ab2d 100644 ---- a/include/sys/socket.h -+++ b/include/sys/socket.h -@@ -16,7 +16,9 @@ - #ifndef _FORTIFY_SYS_SOCKET_H - #define _FORTIFY_SYS_SOCKET_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <sys/socket.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 -diff --git a/include/unistd.h b/include/unistd.h -index d3ab246..71dda84 100644 ---- a/include/unistd.h -+++ b/include/unistd.h -@@ -16,7 +16,9 @@ - #ifndef _FORTIFY_UNISTD_H - #define _FORTIFY_UNISTD_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <unistd.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 -diff --git a/include/wchar.h b/include/wchar.h -index 7394598..3cb6f92 100644 ---- a/include/wchar.h -+++ b/include/wchar.h -@@ -16,13 +16,21 @@ - #ifndef _FORTIFY_WCHAR_H - #define _FORTIFY_WCHAR_H - -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <limits.h> -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <stdlib.h> -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <string.h> -+#ifndef __cplusplus - __extension__ -+#endif - #include_next <wchar.h> - - #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 --- -2.15.0 - diff --git a/legacy/gcc6/001_all_default-ssp-strong.patch b/legacy/gcc6/001_all_default-ssp-strong.patch new file mode 100644 index 000000000..95949eb00 --- /dev/null +++ b/legacy/gcc6/001_all_default-ssp-strong.patch @@ -0,0 +1,215 @@ +# DP: Turn on -fstack-protector by default for C, C++, ObjC, ObjC++. +# DP: Build libgcc using -fno-stack-protector. + +--- + gcc/Makefile.in | 2 ++ + gcc/cp/lang-specs.h | 6 +++--- + gcc/doc/invoke.texi | 4 ++++ + gcc/gcc.c | 18 ++++++++++++++---- + gcc/objc/lang-specs.h | 10 +++++----- + gcc/objcp/lang-specs.h | 8 ++++---- + 6 files changed, 32 insertions(+), 16 deletions(-) + +Index: b/gcc/gcc.c +=================================================================== +--- a/gcc/gcc.c ++++ b/gcc/gcc.c +@@ -858,6 +858,14 @@ proper position among the other output f + #define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G" + #endif + ++#ifndef SSP_DEFAULT_SPEC ++#ifdef TARGET_LIBC_PROVIDES_SSP ++#define SSP_DEFAULT_SPEC "%{!fno-stack-protector:%{!fstack-protector-all:%{!ffreestanding:%{!nostdlib:%{!fstack-protector:-fstack-protector-strong}}}}}" ++#else ++#define SSP_DEFAULT_SPEC "" ++#endif ++#endif ++ + #ifndef LINK_SSP_SPEC + #ifdef TARGET_LIBC_PROVIDES_SSP + #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \ +@@ -1057,6 +1065,7 @@ static const char *cc1_spec = CC1_SPEC; + static const char *cc1plus_spec = CC1PLUS_SPEC; + static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC; + static const char *link_ssp_spec = LINK_SSP_SPEC; ++static const char *ssp_default_spec = SSP_DEFAULT_SPEC; + static const char *asm_spec = ASM_SPEC; + static const char *asm_final_spec = ASM_FINAL_SPEC; + static const char *link_spec = LINK_SPEC; +@@ -1112,7 +1121,7 @@ static const char *cpp_unique_options = + static const char *cpp_options = + "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\ + %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*}\ +- %{undef} %{save-temps*:-fpch-preprocess}"; ++ %{undef} %{save-temps*:-fpch-preprocess} %(ssp_default)"; + + /* This contains cpp options which are not passed when the preprocessor + output will be used by another program. */ +@@ -1301,9 +1310,9 @@ static const struct compiler default_com + %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ + %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\ + cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \ +- %(cc1_options)}\ ++ %(cc1_options) %(ssp_default)}\ + %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ +- cc1 %(cpp_unique_options) %(cc1_options)}}}\ ++ cc1 %(cpp_unique_options) %(cc1_options) %(ssp_default)}}}\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1}, + {"-", + "%{!E:%e-E or -x required when input is from standard input}\ +@@ -1328,7 +1337,7 @@ static const struct compiler default_com + %W{o*:--output-pch=%*}}%V}}}}}}}", 0, 0, 0}, + {".i", "@cpp-output", 0, 0, 0}, + {"@cpp-output", +- "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, ++ "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %(ssp_default) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + {".s", "@assembler", 0, 0, 0}, + {"@assembler", + "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0}, +@@ -1560,6 +1569,7 @@ static struct spec_list static_specs[] = + INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec), + INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec), + INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec), ++ INIT_STATIC_SPEC ("ssp_default", &ssp_default_spec), + INIT_STATIC_SPEC ("endfile", &endfile_spec), + INIT_STATIC_SPEC ("link", &link_spec), + INIT_STATIC_SPEC ("lib", &lib_spec), +Index: b/gcc/cp/lang-specs.h +=================================================================== +--- a/gcc/cp/lang-specs.h ++++ b/gcc/cp/lang-specs.h +@@ -46,7 +46,7 @@ along with GCC; see the file COPYING3. + %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}\ + cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}\ + %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}\ +- %(cc1_options) %2\ ++ %(cc1_options) %(ssp_default) %2\ + %{!fsyntax-only:-o %g.s \ + %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\ + %W{o*:--output-pch=%*}}%V}}}}", +@@ -58,11 +58,11 @@ along with GCC; see the file COPYING3. + %(cpp_options) %2 -o %{save-temps*:%b.ii} %{!save-temps*:%g.ii} \n}\ + cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}\ + %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}\ +- %(cc1_options) %2\ ++ %(cc1_options) %(ssp_default) %2\ + %{!fsyntax-only:%(invoke_as)}}}}", + CPLUSPLUS_CPP_SPEC, 0, 0}, + {".ii", "@c++-cpp-output", 0, 0, 0}, + {"@c++-cpp-output", + "%{!M:%{!MM:%{!E:\ +- cc1plus -fpreprocessed %i %(cc1_options) %2\ ++ cc1plus -fpreprocessed %i %(cc1_options) %(ssp_default) %2\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, +Index: b/gcc/params.def +=================================================================== +--- a/gcc/params.def ++++ b/gcc/params.def +@@ -673,7 +673,7 @@ DEFPARAM (PARAM_INTEGER_SHARE_LIMIT, + DEFPARAM (PARAM_SSP_BUFFER_SIZE, + "ssp-buffer-size", + "The lower bound for a buffer to be considered for stack smashing protection.", +- 8, 1, 0) ++ 4, 1, 0) + + DEFPARAM (PARAM_MIN_SIZE_FOR_STACK_SHARING, + "min-size-for-stack-sharing", +Index: b/gcc/objc/lang-specs.h +=================================================================== +--- a/gcc/objc/lang-specs.h ++++ b/gcc/objc/lang-specs.h +@@ -29,9 +29,9 @@ along with GCC; see the file COPYING3. + %{traditional|traditional-cpp:\ + %eGNU Objective C no longer supports traditional compilation}\ + %{save-temps*|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps*:%b.mi} %{!save-temps*:%g.mi} \n\ +- cc1obj -fpreprocessed %{save-temps*:%b.mi} %{!save-temps*:%g.mi} %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}\ ++ cc1obj -fpreprocessed %{save-temps*:%b.mi} %{!save-temps*:%g.mi} %(cc1_options) %(ssp_default) %{print-objc-runtime-info} %{gen-decls}}\ + %{!save-temps*:%{!no-integrated-cpp:\ +- cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}}}\ ++ cc1obj %(cpp_unique_options) %(cc1_options) %(ssp_default) %{print-objc-runtime-info} %{gen-decls}}}\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + {"@objective-c-header", + "%{E|M|MM:cc1obj -E %{traditional|traditional-cpp:-traditional-cpp}\ +@@ -40,18 +40,18 @@ along with GCC; see the file COPYING3. + %{traditional|traditional-cpp:\ + %eGNU Objective C no longer supports traditional compilation}\ + %{save-temps*|no-integrated-cpp:cc1obj -E %(cpp_options) -o %{save-temps*:%b.mi} %{!save-temps*:%g.mi} \n\ +- cc1obj -fpreprocessed %b.mi %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\ ++ cc1obj -fpreprocessed %b.mi %(cc1_options) %(ssp_default) %{print-objc-runtime-info} %{gen-decls}\ + -o %g.s %{!o*:--output-pch=%i.gch}\ + %W{o*:--output-pch=%*}%V}\ + %{!save-temps*:%{!no-integrated-cpp:\ +- cc1obj %(cpp_unique_options) %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\ ++ cc1obj %(cpp_unique_options) %(cc1_options) %(ssp_default) %{print-objc-runtime-info} %{gen-decls}\ + -o %g.s %{!o*:--output-pch=%i.gch}\ + %W{o*:--output-pch=%*}%V}}}}}", 0, 0, 0}, + {".mi", "@objective-c-cpp-output", 0, 0, 0}, + {"@objective-c-cpp-output", +- "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\ ++ "%{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %(ssp_default) %{print-objc-runtime-info} %{gen-decls}\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + {"@objc-cpp-output", + "%nobjc-cpp-output is deprecated; please use objective-c-cpp-output instead\n\ +- %{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %{print-objc-runtime-info} %{gen-decls}\ ++ %{!M:%{!MM:%{!E:cc1obj -fpreprocessed %i %(cc1_options) %(ssp_default) %{print-objc-runtime-info} %{gen-decls}\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, +Index: b/gcc/objcp/lang-specs.h +=================================================================== +--- a/gcc/objcp/lang-specs.h ++++ b/gcc/objcp/lang-specs.h +@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. + %(cpp_options) %2 -o %{save-temps*:%b.mii} %{!save-temps*:%g.mii} \n}\ + cc1objplus %{save-temps*|no-integrated-cpp:-fpreprocessed %{save-temps*:%b.mii} %{!save-temps*:%g.mii}}\ + %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}\ +- %(cc1_options) %2\ ++ %(cc1_options) %(ssp_default) %2\ + -o %g.s %{!o*:--output-pch=%i.gch} %W{o*:--output-pch=%*}%V}}}", + CPLUSPLUS_CPP_SPEC, 0, 0}, + {"@objective-c++", +@@ -46,16 +46,16 @@ along with GCC; see the file COPYING3. + %(cpp_options) %2 -o %{save-temps*:%b.mii} %{!save-temps*:%g.mii} \n}\ + cc1objplus %{save-temps*|no-integrated-cpp:-fpreprocessed %{save-temps*:%b.mii} %{!save-temps*:%g.mii}}\ + %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}\ +- %(cc1_options) %2\ ++ %(cc1_options) %(ssp_default) %2\ + %{!fsyntax-only:%(invoke_as)}}}}", + CPLUSPLUS_CPP_SPEC, 0, 0}, + {".mii", "@objective-c++-cpp-output", 0, 0, 0}, + {"@objective-c++-cpp-output", + "%{!M:%{!MM:%{!E:\ +- cc1objplus -fpreprocessed %i %(cc1_options) %2\ ++ cc1objplus -fpreprocessed %i %(cc1_options) %(ssp_default) %2\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + {"@objc++-cpp-output", + "%nobjc++-cpp-output is deprecated; please use objective-c++-cpp-output instead\n\ + %{!M:%{!MM:%{!E:\ +- cc1objplus -fpreprocessed %i %(cc1_options) %2\ ++ cc1objplus -fpreprocessed %i %(cc1_options) %(ssp_default) %2\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, +Index: b/gcc/doc/invoke.texi +=================================================================== +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -9247,6 +9247,9 @@ + The minimum size of variables taking part in stack slot sharing when not + optimizing. The default value is 32. + ++The Alpine Linux default is "4", to increase ++the number of functions protected by the stack protector. ++ + @item max-jump-thread-duplication-stmts + Maximum number of statements allowed in a block that needs to be + duplicated when threading jumps. +@@ -10185,6 +10188,11 @@ + Like @option{-fstack-protector} but includes additional functions to + be protected --- those that have local array definitions, or have + references to local frame addresses. ++ ++NOTE: In Alpine Linux, ++@option{-fstack-protector-strong} is enabled by default for C, ++C++, ObjC, ObjC++, if none of @option{-fno-stack-protector}, ++@option{-nostdlib}, nor @option{-ffreestanding} are found. + + @item -fstack-protector-explicit + @opindex fstack-protector-explicit diff --git a/legacy/gcc6/002_all_default-relro.patch b/legacy/gcc6/002_all_default-relro.patch new file mode 100644 index 000000000..c461017dc --- /dev/null +++ b/legacy/gcc6/002_all_default-relro.patch @@ -0,0 +1,33 @@ +# Turn on -Wl,-z,relro,-z,now by default. + +--- + gcc/doc/invoke.texi | 3 +++ + gcc/gcc.c | 1 + + 2 files changed, 4 insertions(+), 0 deletions(-) + +Index: b/gcc/doc/invoke.texi +=================================================================== +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -11424,6 +11424,9 @@ For example, @option{-Wl,-Map,output.map + linker. When using the GNU linker, you can also get the same effect with + @option{-Wl,-Map=output.map}. + ++NOTE: In Alpine Linux, for LDFLAGS, the option ++@option{-Wl,-z,relro,now} is used. To disable, use @option{-Wl,-z,norelro}. ++ + @item -u @var{symbol} + @opindex u + Pretend the symbol @var{symbol} is undefined, to force linking of +Index: b/gcc/gcc.c +=================================================================== +--- a/gcc/gcc.c ++++ b/gcc/gcc.c +@@ -890,6 +890,7 @@ proper position among the other output f + "%{flto|flto=*:%<fcompare-debug*} \ + %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \ + "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \ ++ "-z relro -z now " \ + "%X %{o*} %{e*} %{N} %{n} %{r}\ + %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} " VTABLE_VERIFICATION_SPEC " \ + %{static:} %{L*} %(mfwrap) %(link_libgcc) " SANITIZER_EARLY_SPEC " %o\ diff --git a/legacy/gcc6/003_all_default-fortify-source.patch b/legacy/gcc6/003_all_default-fortify-source.patch new file mode 100644 index 000000000..6ca803343 --- /dev/null +++ b/legacy/gcc6/003_all_default-fortify-source.patch @@ -0,0 +1,40 @@ +# DP: Turn on -D_FORTIFY_SOURCE=2 by default for C, C++, ObjC, ObjC++, +# DP: if the optimization level is > 0 + +--- + gcc/doc/invoke.texi | 6 ++++++ + gcc/c-family/c-cppbuiltin.c | 3 + + 2 files changed, 9 insertions(+), 0 deletions(-) + +Index: b/gcc/doc/invoke.texi +=================================================================== +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -7840,6 +7840,12 @@ also turns on the following optimization + Please note the warning under @option{-fgcse} about + invoking @option{-O2} on programs that use computed gotos. + ++NOTE: In Alpine Linux, @option{-D_FORTIFY_SOURCE=2} is ++set by default, and is activated when @option{-O} is set to 2 or higher. ++This enables additional compile-time and run-time checks for several libc ++functions. To disable, specify either @option{-U_FORTIFY_SOURCE} or ++@option{-D_FORTIFY_SOURCE=0}. ++ + @item -O3 + @opindex O3 + Optimize yet more. @option{-O3} turns on all optimizations specified +Index: b/gcc/c-family/c-cppbuiltin.c +=================================================================== +--- a/gcc/c-family/c-cppbuiltin.c ++++ b/gcc/c-family/c-cppbuiltin.c +@@ -1176,6 +1176,10 @@ c_cpp_builtins (cpp_reader *pfile) + builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0); + builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0); + ++ /* Fortify Source enabled by default for optimization levels > 0 */ ++ if (optimize) ++ builtin_define_with_int_value ("_FORTIFY_SOURCE", 2); ++ + /* Misc. */ + if (flag_gnu89_inline) + cpp_define (pfile, "__GNUC_GNU_INLINE__"); diff --git a/legacy/gcc6/005_all_default-as-needed.patch b/legacy/gcc6/005_all_default-as-needed.patch new file mode 100644 index 000000000..ee4f7962a --- /dev/null +++ b/legacy/gcc6/005_all_default-as-needed.patch @@ -0,0 +1,241 @@ +# DP: On linux targets pass --as-needed by default to the linker, but always +# DP: link the sanitizer libraries with --no-as-needed. + +--- a/gcc/gcc.c ++++ b/gcc/gcc.c +@@ -568,8 +568,11 @@ proper position among the other output f + #ifdef LIBTSAN_EARLY_SPEC + #define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS + #elif defined(HAVE_LD_STATIC_DYNAMIC) +-#define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \ +- "} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}" \ ++#define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION "}" \ ++ " %{!static-libtsan:%{!fuse-ld=gold:--push-state }--no-as-needed}" \ ++ " -ltsan " \ ++ " %{static-libtsan:" LD_DYNAMIC_OPTION "}" \ ++ " %{!static-libtsan:%{fuse-ld=gold:--as-needed;:--pop-state}}" \ + STATIC_LIBTSAN_LIBS + #else + #define LIBTSAN_SPEC "-ltsan" STATIC_LIBTSAN_LIBS +--- a/gcc/config/gnu-user.h ++++ b/gcc/config/gnu-user.h +@@ -124,13 +124,13 @@ + #define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \ + "%{static-libasan:%{!shared:" \ + LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \ +- LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}" ++ LD_DYNAMIC_OPTION "}}%{!static-libasan:%{!fuse-ld=gold:--push-state} --no-as-needed -lasan %{fuse-ld=gold:--as-needed;:--pop-state}}" + #undef LIBTSAN_EARLY_SPEC + #define LIBTSAN_EARLY_SPEC "%{static-libtsan:%{!shared:" \ + LD_STATIC_OPTION " --whole-archive -ltsan --no-whole-archive " \ +- LD_DYNAMIC_OPTION "}}%{!static-libtsan:-ltsan}" ++ LD_DYNAMIC_OPTION "}}%{!static-libtsan:%{!fuse-ld=gold:--push-state} --no-as-needed -ltsan %{fuse-ld=gold:--as-needed;:--pop-state}}" + #undef LIBLSAN_EARLY_SPEC + #define LIBLSAN_EARLY_SPEC "%{static-liblsan:%{!shared:" \ + LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \ +- LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}" ++ LD_DYNAMIC_OPTION "}}%{!static-liblsan:%{!fuse-ld=gold:--push-state} --no-as-needed -llsan %{fuse-ld=gold:--as-needed;:--pop-state}}" + #endif +Index: b/gcc/config/aarch64/aarch64-linux.h +=================================================================== +--- a/gcc/config/aarch64/aarch64-linux.h ++++ b/gcc/config/aarch64/aarch64-linux.h +@@ -36,5 +36,6 @@ + + #define LINUX_TARGET_LINK_SPEC "%{h*} \ ++ --as-needed \ + %{static:-Bstatic} \ + %{shared:-shared} \ + %{symbolic:-Bsymbolic} \ +Index: b/gcc/config/ia64/linux.h +=================================================================== +--- a/gcc/config/ia64/linux.h ++++ b/gcc/config/ia64/linux.h +@@ -58,7 +58,7 @@ do { \ + #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-ia64.so.2" + + #undef LINK_SPEC +-#define LINK_SPEC "\ ++#define LINK_SPEC " --as-needed \ + %{shared:-shared} \ + %{!shared: \ + %{!static: \ +Index: b/gcc/config/sparc/linux.h +=================================================================== +--- a/gcc/config/sparc/linux.h ++++ b/gcc/config/sparc/linux.h +@@ -86,7 +86,7 @@ extern const char *host_detect_local_cpu + #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2" + + #undef LINK_SPEC +-#define LINK_SPEC "-m elf32_sparc %{shared:-shared} \ ++#define LINK_SPEC "-m elf32_sparc --as-needed %{shared:-shared} \ + %{!mno-relax:%{!r:-relax}} \ + %{!shared: \ + %{!static: \ +Index: b/gcc/config/s390/linux.h +=================================================================== +--- a/gcc/config/s390/linux.h ++++ b/gcc/config/s390/linux.h +@@ -65,7 +65,7 @@ along with GCC; see the file COPYING3. + + #undef LINK_SPEC + #define LINK_SPEC \ +- "%{m31:-m elf_s390}%{m64:-m elf64_s390} \ ++ "%{m31:-m elf_s390}%{m64:-m elf64_s390} --as-needed \ + %{shared:-shared} \ + %{!shared: \ + %{static:-static} \ +Index: b/gcc/config/rs6000/linux64.h +=================================================================== +--- a/gcc/config/rs6000/linux64.h ++++ b/gcc/config/rs6000/linux64.h +@@ -466,12 +466,12 @@ extern int dot_symbols; + " -m elf64ppc") + #endif + +-#define LINK_OS_LINUX_SPEC32 LINK_OS_LINUX_EMUL32 " %{!shared: %{!static: \ ++#define LINK_OS_LINUX_SPEC32 LINK_OS_LINUX_EMUL32 " --as-needed %{!shared: %{!static: \ + %{rdynamic:-export-dynamic} \ + -dynamic-linker " GNU_USER_DYNAMIC_LINKER32 "}} \ + %(link_os_extra_spec32)" + +-#define LINK_OS_LINUX_SPEC64 LINK_OS_LINUX_EMUL64 " %{!shared: %{!static: \ ++#define LINK_OS_LINUX_SPEC64 LINK_OS_LINUX_EMUL64 " --as-needed %{!shared: %{!static: \ + %{rdynamic:-export-dynamic} \ + -dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "}} \ + %(link_os_extra_spec64)" +Index: b/gcc/config/rs6000/sysv4.h +=================================================================== +--- a/gcc/config/rs6000/sysv4.h ++++ b/gcc/config/rs6000/sysv4.h +@@ -784,7 +784,7 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEF + CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER, \ + MUSL_DYNAMIC_LINKER) + +-#define LINK_OS_LINUX_SPEC "-m elf32ppclinux %{!shared: %{!static: \ ++#define LINK_OS_LINUX_SPEC "-m elf32ppclinux --as-needed %{!shared: %{!static: \ + %{rdynamic:-export-dynamic} \ + -dynamic-linker " GNU_USER_DYNAMIC_LINKER "}}" + +Index: b/gcc/config/i386/gnu-user64.h +=================================================================== +--- a/gcc/config/i386/gnu-user64.h ++++ b/gcc/config/i386/gnu-user64.h +@@ -57,5 +57,6 @@ see the files COPYING3 and COPYING.RUNTI + %{" SPEC_32 ":-m " GNU_USER_LINK_EMULATION32 "} \ + %{" SPEC_X32 ":-m " GNU_USER_LINK_EMULATIONX32 "} \ ++ --as-needed \ + %{shared:-shared} \ + %{!shared: \ + %{!static: \ +Index: b/gcc/config/i386/gnu-user.h +=================================================================== +--- a/gcc/config/i386/gnu-user.h ++++ b/gcc/config/i386/gnu-user.h +@@ -74,7 +74,7 @@ along with GCC; see the file COPYING3. + { "link_emulation", GNU_USER_LINK_EMULATION },\ + { "dynamic_linker", GNU_USER_DYNAMIC_LINKER } + +-#define GNU_USER_TARGET_LINK_SPEC "-m %(link_emulation) %{shared:-shared} \ ++#define GNU_USER_TARGET_LINK_SPEC "-m %(link_emulation) --as-needed %{shared:-shared} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ +Index: b/gcc/config/alpha/linux-elf.h +=================================================================== +--- a/gcc/config/alpha/linux-elf.h ++++ b/gcc/config/alpha/linux-elf.h +@@ -37,7 +37,7 @@ along with GCC; see the file COPYING3. + + #define ELF_DYNAMIC_LINKER GNU_USER_DYNAMIC_LINKER + +-#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \ ++#define LINK_SPEC "-m elf64alpha --as-needed %{G*} %{relax:-relax} \ + %{O*:-O3} %{!O*:-O1} \ + %{shared:-shared} \ + %{!shared: \ +Index: b/gcc/config/arm/linux-elf.h +=================================================================== +--- a/gcc/config/arm/linux-elf.h ++++ b/gcc/config/arm/linux-elf.h +@@ -73,5 +73,6 @@ + %{!shared:-dynamic-linker " GNU_USER_DYNAMIC_LINKER "}} \ + -X \ ++ --as-needed \ + %{mbig-endian:-EB} %{mlittle-endian:-EL}" \ + SUBTARGET_EXTRA_LINK_SPEC + +Index: b/gcc/config/mips/gnu-user.h +=================================================================== +--- a/gcc/config/mips/gnu-user.h ++++ b/gcc/config/mips/gnu-user.h +@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. + #undef GNU_USER_TARGET_LINK_SPEC + #define GNU_USER_TARGET_LINK_SPEC "\ + %{G*} %{EB} %{EL} %{mips*} %{shared} \ ++ -as-needed \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ +Index: b/libjava/Makefile.am +=================================================================== +--- a/libjava/Makefile.am ++++ b/libjava/Makefile.am +@@ -627,14 +631,14 @@ + rm .libs/libgcj_bc.so; \ + mv .libs/libgcj_bc.so.1.0.0 .libs/libgcj_bc.so; \ + $(libgcj_bc_dummy_LINK) -xc /dev/null -Wl,-soname,libgcj_bc.so.1 \ +- -o .libs/libgcj_bc.so.1.0.0 -lgcj || exit; \ ++ -o .libs/libgcj_bc.so.1.0.0 -Wl,--no-as-needed -lgcj || exit; \ + rm .libs/libgcj_bc.so.1; \ + $(LN_S) libgcj_bc.so.1.0.0 .libs/libgcj_bc.so.1 + + ## This rule creates the libgcj_bc library that is actually installed. + install/libgcj_bc.la: $(libgcj_bc_la_OBJECTS) $(libgcj_bc_la_DEPENDENCIES) install/$(am__dirstamp) + $(libgcj_bc_la_LINK) $(am_libgcj_bc_la_rpath) $(libgcj_bc_la_LDFLAGS) \ +- $(libgcj_bc_la_OBJECTS) $(libgcj_bc_la_LIBADD) $(LIBS) ++ $(libgcj_bc_la_OBJECTS) $(libgcj_bc_la_LIBADD) $(LIBS) -Wl,--no-as-needed -lgcj + + ## Note that property_files is defined in sources.am. + propertyo_files = $(patsubst classpath/resource/%,%,$(addsuffix .lo,$(property_files))) +@@ -762,7 +766,7 @@ + rm $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so; \ + mv $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1.0.0 $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so; \ + $(libgcj_bc_dummy_LINK) -xc /dev/null -Wl,-soname,libgcj_bc.so.1 \ +- -o $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1.0.0 -lgcj || exit; \ ++ -o $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1.0.0 -Wl,--no-as-needed -lgcj || exit; \ + rm $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1; \ + $(LN_S) libgcj_bc.so.1.0.0 $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1; \ + rm $(DESTDIR)$(toolexeclibdir)/libgcj_bc.la; + +Index: b/libjava/Makefile.in +=================================================================== +--- a/libjava/Makefile.in ++++ b/libjava/Makefile.in +@@ -10644,13 +10648,13 @@ + rm .libs/libgcj_bc.so; \ + mv .libs/libgcj_bc.so.1.0.0 .libs/libgcj_bc.so; \ + $(libgcj_bc_dummy_LINK) -xc /dev/null -Wl,-soname,libgcj_bc.so.1 \ +- -o .libs/libgcj_bc.so.1.0.0 -lgcj || exit; \ ++ -o .libs/libgcj_bc.so.1.0.0 -Wl,--no-as-needed -lgcj || exit; \ + rm .libs/libgcj_bc.so.1; \ + $(LN_S) libgcj_bc.so.1.0.0 .libs/libgcj_bc.so.1 + + install/libgcj_bc.la: $(libgcj_bc_la_OBJECTS) $(libgcj_bc_la_DEPENDENCIES) install/$(am__dirstamp) + $(libgcj_bc_la_LINK) $(am_libgcj_bc_la_rpath) $(libgcj_bc_la_LDFLAGS) \ +- $(libgcj_bc_la_OBJECTS) $(libgcj_bc_la_LIBADD) $(LIBS) ++ $(libgcj_bc_la_OBJECTS) $(libgcj_bc_la_LIBADD) $(LIBS) -Wl,--no-as-needed -lgcj + + $(propertyo_files): %.lo: classpath/resource/% + $(mkinstalldirs) `dirname $@`; \ +@@ -12494,7 +12498,7 @@ + @USE_LIBGCJ_BC_TRUE@ rm $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so; \ + @USE_LIBGCJ_BC_TRUE@ mv $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1.0.0 $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so; \ + @USE_LIBGCJ_BC_TRUE@ $(libgcj_bc_dummy_LINK) -xc /dev/null -Wl,-soname,libgcj_bc.so.1 \ +-@USE_LIBGCJ_BC_TRUE@ -o $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1.0.0 -lgcj || exit; \ ++@USE_LIBGCJ_BC_TRUE@ -o $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1.0.0 -Wl,--no-as-needed -lgcj || exit; \ + @USE_LIBGCJ_BC_TRUE@ rm $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1; \ + @USE_LIBGCJ_BC_TRUE@ $(LN_S) libgcj_bc.so.1.0.0 $(DESTDIR)$(toolexeclibdir)/libgcj_bc.so.1; \ + @USE_LIBGCJ_BC_TRUE@ rm $(DESTDIR)$(toolexeclibdir)/libgcj_bc.la; + diff --git a/legacy/gcc6/011_all_default-warn-format-security.patch b/legacy/gcc6/011_all_default-warn-format-security.patch new file mode 100644 index 000000000..a58383a8e --- /dev/null +++ b/legacy/gcc6/011_all_default-warn-format-security.patch @@ -0,0 +1,43 @@ +Enable -Wformat and -Wformat-security by default. + + +--- a/gcc/c-family/c.opt ++++ b/gcc/c-family/c.opt +@@ -412,7 +412,7 @@ C ObjC C++ ObjC++ Var(warn_format_nonliteral) Warning LangEnabledBy(C ObjC C++ O + Warn about format strings that are not literals + + Wformat-security +-C ObjC C++ ObjC++ Var(warn_format_security) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0) ++C ObjC C++ ObjC++ Var(warn_format_security) Init(1) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0) + Warn about possible security problems with format functions + + Wformat-y2k +@@ -424,7 +424,7 @@ C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning LangEnabledBy(C ObjC C++ + Warn about zero-length formats + + Wformat= +-C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) ++C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Init(1) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) + Warn about printf/scanf/strftime/strfmon format string anomalies + + Wignored-qualifiers +--- a/gcc/doc/gcc.info ++++ b/gcc/doc/gcc.info +@@ -3451,6 +3451,8 @@ compiler warns that an unrecognized option is present. + '-Wno-format-contains-nul', '-Wno-format-extra-args', and + '-Wno-format-zero-length'. '-Wformat' is enabled by '-Wall'. + ++ This option is enabled by default in Alpine Linux. ++ + '-Wno-format-contains-nul' + If '-Wformat' is specified, do not warn about format strings + that contain NUL bytes. +@@ -3496,6 +3498,8 @@ compiler warns that an unrecognized option is present. + future warnings may be added to '-Wformat-security' that are + not included in '-Wformat-nonliteral'.) + ++ This option is enabled by default in Alpine Linux. ++ + '-Wformat-y2k' + If '-Wformat' is specified, also warn about 'strftime' formats + that may yield only a two-digit year. diff --git a/legacy/gcc6/012_all_default-warn-trampolines.patch b/legacy/gcc6/012_all_default-warn-trampolines.patch new file mode 100644 index 000000000..9ab4378d4 --- /dev/null +++ b/legacy/gcc6/012_all_default-warn-trampolines.patch @@ -0,0 +1,25 @@ +Enable -Wtrampolines by default. + + +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -648,7 +648,7 @@ Common Var(warn_system_headers) Warning + Do not suppress warnings from system headers + + Wtrampolines +-Common Var(warn_trampolines) Warning ++Common Var(warn_trampolines) Init(1) Warning + Warn whenever a trampoline is generated + + Wtype-limits +--- a/gcc/doc/gcc.info ++++ b/gcc/doc/gcc.info +@@ -4021,6 +4021,8 @@ compiler warns that an unrecognized option is present. + and thus requires the stack to be made executable in order for the + program to work properly. + ++ This warning is enabled by default in Gentoo. ++ + '-Wfloat-equal' + Warn if floating-point values are used in equality comparisons. + diff --git a/legacy/gcc6/020_all_msgfmt-libstdc++-link.patch b/legacy/gcc6/020_all_msgfmt-libstdc++-link.patch new file mode 100644 index 000000000..a70ea50a0 --- /dev/null +++ b/legacy/gcc6/020_all_msgfmt-libstdc++-link.patch @@ -0,0 +1,39 @@ +Ensure that msgfmt doesn't encounter problems during gcc bootstrapping. + +Solves error messages like the following: + +msgfmt: /var/tmp/portage/sys-devel/gcc-4.1.2/work/build/./gcc/libgcc_s.so.1: version `GCC_4.2.0' not found (required by /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/libstdc++.so.6) + +The libgcc_s.so used during build doesn't satisfy the needs of the +libstdc++.so that msgfmt is linked against. On the other hand, msgfmt +is used as a stand-alone application here, and what library it uses +behind the scenes is of no concern to the gcc build process. +Therefore, simply invoking it "as usual", i.e. without any special +library path, will make it work as expected here. + +2011-09-19 Martin von Gagern + +References: +https://bugs.gentoo.org/372377 +https://bugs.gentoo.org/295480 + +--- gcc-4.1.2.orig/libstdc++-v3/po/Makefile.am ++++ gcc-4.1.2/libstdc++-v3/po/Makefile.am +@@ -39,6 +39,7 @@ MSGFMT = msgfmt + EXTRA_DIST = string_literals.cc POTFILES.in $(PACKAGE).pot $(LOCALE_IN) + + .po.mo: ++ env --unset=LD_LIBRARY_PATH \ + $(MSGFMT) -o $@ $< + + all-local: all-local-$(USE_NLS) +--- gcc-4.1.2.orig/libstdc++-v3/po/Makefile.in ++++ gcc-4.1.2/libstdc++-v3/po/Makefile.in +@@ -419,6 +419,7 @@ uninstall-am: uninstall-info-am + + + .po.mo: ++ env --unset=LD_LIBRARY_PATH \ + $(MSGFMT) -o $@ $< + + all-local: all-local-$(USE_NLS) diff --git a/legacy/gcc6/050_all_libiberty-asprintf.patch b/legacy/gcc6/050_all_libiberty-asprintf.patch new file mode 100644 index 000000000..bee0c4c23 --- /dev/null +++ b/legacy/gcc6/050_all_libiberty-asprintf.patch @@ -0,0 +1,18 @@ +2008-07-25 Magnus Granberg <zorry@ume.nu> + + * include/libiberty.h (asprintf): Don't declare if defined as a macro + +--- a/include/libiberty.h ++++ b/include/libiberty.h +@@ -609,8 +609,11 @@ extern int pwait (int, int *, int); + /* Like sprintf but provides a pointer to malloc'd storage, which must + be freed by the caller. */ + ++/* asprintf may be declared as a macro by glibc with __USE_FORTIFY_LEVEL. */ ++#ifndef asprintf + extern int asprintf (char **, const char *, ...) ATTRIBUTE_PRINTF_2; + #endif ++#endif + + #if !HAVE_DECL_VASPRINTF + /* Like vsprintf but provides a pointer to malloc'd storage, which diff --git a/legacy/gcc6/051_all_libiberty-pic.patch b/legacy/gcc6/051_all_libiberty-pic.patch new file mode 100644 index 000000000..b6160a730 --- /dev/null +++ b/legacy/gcc6/051_all_libiberty-pic.patch @@ -0,0 +1,10 @@ +--- a/libiberty/Makefile.in ++++ b/libiberty/Makefile.in +@@ -246,6 +246,7 @@ $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) + $(AR) $(AR_FLAGS) $(TARGETLIB) \ + $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS); \ + $(RANLIB) $(TARGETLIB); \ ++ cp $(TARGETLIB) ../ ; \ + cd ..; \ + else true; fi + diff --git a/legacy/gcc6/053_all_libitm-no-fortify-source.patch b/legacy/gcc6/053_all_libitm-no-fortify-source.patch new file mode 100644 index 000000000..5ab15afc3 --- /dev/null +++ b/legacy/gcc6/053_all_libitm-no-fortify-source.patch @@ -0,0 +1,27 @@ +https://bugs.gentoo.org/508852 +https://gcc.gnu.org/PR61164 + +2014-04-27 Magnus Granberg <zorry@gentoo.org> + + #508852 + * libitm/configure.tgt: Disable FORTIFY + +--- a/libitm/configure.tgt ++++ b/libitm/configure.tgt +@@ -43,6 +43,16 @@ if test "$gcc_cv_have_tls" = yes ; then + esac + fi + ++# FIXME: error: inlining failed in call to always_inline ++# ‘int vfprintf(FILE*, const char*, __va_list_tag*)’ ++# : function body can be overwritten at link time ++# Disable Fortify in libitm for now. #508852 ++case "${target}" in ++ *-*-linux*) ++ XCFLAGS="${XCFLAGS} -U_FORTIFY_SOURCE" ++ ;; ++esac ++ + # Map the target cpu to an ARCH sub-directory. At the same time, + # work out any special compilation flags as necessary. + case "${target_cpu}" in diff --git a/legacy/gcc6/067_all_gcc-poison-system-directories.patch b/legacy/gcc6/067_all_gcc-poison-system-directories.patch new file mode 100644 index 000000000..103671617 --- /dev/null +++ b/legacy/gcc6/067_all_gcc-poison-system-directories.patch @@ -0,0 +1,194 @@ +http://cgit.openembedded.org/openembedded-core/plain/meta/recipes-devtools/gcc/gcc-6.1/0010-gcc-poison-system-directories.patch + +From d76250323dad69212c958e4857a98d99ab51a39e Mon Sep 17 00:00:00 2001 +From: Khem Raj <raj.khem@gmail.com> +Date: Fri, 29 Mar 2013 08:59:00 +0400 +Subject: [PATCH 10/46] gcc: poison-system-directories + +Signed-off-by: Khem Raj <raj.khem@gmail.com> + +Upstream-Status: Inappropriate [distribution: codesourcery] +--- + gcc/common.opt | 4 ++++ + gcc/config.in | 6 ++++++ + gcc/configure | 16 ++++++++++++++++ + gcc/configure.ac | 10 ++++++++++ + gcc/doc/invoke.texi | 9 +++++++++ + gcc/gcc.c | 2 ++ + gcc/incpath.c | 19 +++++++++++++++++++ + 7 files changed, 66 insertions(+) + +diff --git a/gcc/common.opt b/gcc/common.opt +index 67048db..733185c 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -659,6 +659,10 @@ Wreturn-local-addr + Common Var(warn_return_local_addr) Init(1) Warning + Warn about returning a pointer/reference to a local or temporary variable. + ++Wpoison-system-directories ++Common Var(flag_poison_system_directories) Init(1) Warning ++Warn for -I and -L options using system directories if cross compiling ++ + Wshadow + Common Var(warn_shadow) Warning + Warn when one local variable shadows another. +diff --git a/gcc/config.in b/gcc/config.in +index 115cb61..105b30f 100644 +--- a/gcc/config.in ++++ b/gcc/config.in +@@ -187,6 +187,12 @@ + #endif + + ++/* Define to warn for use of native system header directories */ ++#ifndef USED_FOR_TARGET ++#undef ENABLE_POISON_SYSTEM_DIRECTORIES ++#endif ++ ++ + /* Define if you want all operations on RTL (the basic data structure of the + optimizer and back end) to be checked for dynamic type safety at runtime. + This is quite expensive. */ +diff --git a/gcc/configure b/gcc/configure +index 1c6e340..8f83152 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -942,6 +942,7 @@ with_system_zlib + enable_maintainer_mode + enable_link_mutex + enable_version_specific_runtime_libs ++enable_poison_system_directories + enable_plugin + enable_host_shared + enable_libquadmath_support +@@ -1681,6 +1682,8 @@ Optional Features: + --enable-version-specific-runtime-libs + specify that runtime libraries should be installed + in a compiler-specific directory ++ --enable-poison-system-directories ++ warn for use of native system header directories + --enable-plugin enable plugin support + --enable-host-shared build host code as shared libraries + --disable-libquadmath-support +@@ -28908,6 +28911,19 @@ if test "${enable_version_specific_runtime_libs+set}" = set; then : + fi + + ++# Check whether --enable-poison-system-directories was given. ++if test "${enable_poison_system_directories+set}" = set; then : ++ enableval=$enable_poison_system_directories; ++else ++ enable_poison_system_directories=no ++fi ++ ++if test "x${enable_poison_system_directories}" = "xyes"; then ++ ++$as_echo "#define ENABLE_POISON_SYSTEM_DIRECTORIES 1" >>confdefs.h ++ ++fi ++ + # Substitute configuration variables + + +diff --git a/gcc/configure.ac b/gcc/configure.ac +index 6c1dcd9..0fccaef 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -5861,6 +5861,16 @@ AC_ARG_ENABLE(version-specific-runtime-libs, + [specify that runtime libraries should be + installed in a compiler-specific directory])]) + ++AC_ARG_ENABLE([poison-system-directories], ++ AS_HELP_STRING([--enable-poison-system-directories], ++ [warn for use of native system header directories]),, ++ [enable_poison_system_directories=no]) ++if test "x${enable_poison_system_directories}" = "xyes"; then ++ AC_DEFINE([ENABLE_POISON_SYSTEM_DIRECTORIES], ++ [1], ++ [Define to warn for use of native system header directories]) ++fi ++ + # Substitute configuration variables + AC_SUBST(subdirs) + AC_SUBST(srcdir) +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index 821f8fd..8bb49e7 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -284,6 +284,7 @@ Objective-C and Objective-C++ Dialects}. + -Wparentheses -Wno-pedantic-ms-format @gol + -Wplacement-new -Wplacement-new=@var{n} @gol + -Wpointer-arith -Wno-pointer-to-int-cast @gol ++-Wno-poison-system-directories @gol + -Wno-pragmas -Wredundant-decls -Wno-return-local-addr @gol + -Wreturn-type -Wsequence-point -Wshadow -Wno-shadow-ivar @gol + -Wshift-overflow -Wshift-overflow=@var{n} @gol +@@ -4723,6 +4724,14 @@ made up of data only and thus requires no special treatment. But, for + most targets, it is made up of code and thus requires the stack to be + made executable in order for the program to work properly. + ++@item -Wno-poison-system-directories ++@opindex Wno-poison-system-directories ++Do not warn for @option{-I} or @option{-L} options using system ++directories such as @file{/usr/include} when cross compiling. This ++option is intended for use in chroot environments when such ++directories contain the correct headers and libraries for the target ++system rather than the host. ++ + @item -Wfloat-equal + @opindex Wfloat-equal + @opindex Wno-float-equal +diff --git a/gcc/gcc.c b/gcc/gcc.c +index 1af5920..4cfef7f 100644 +--- a/gcc/gcc.c ++++ b/gcc/gcc.c +@@ -1017,6 +1017,8 @@ proper position among the other output files. */ + "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \ + "%X %{o*} %{e*} %{N} %{n} %{r}\ + %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} \ ++ %{Wno-poison-system-directories:--no-poison-system-directories} \ ++ %{Werror=poison-system-directories:--error-poison-system-directories} \ + %{static:} %{L*} %(mfwrap) %(link_libgcc) " \ + VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o " CHKP_SPEC " \ + %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\ +diff --git a/gcc/incpath.c b/gcc/incpath.c +index ea40f4a..856da41 100644 +--- a/gcc/incpath.c ++++ b/gcc/incpath.c +@@ -26,6 +26,7 @@ + #include "intl.h" + #include "incpath.h" + #include "cppdefault.h" ++#include "diagnostic-core.h" + + /* Microsoft Windows does not natively support inodes. + VMS has non-numeric inodes. */ +@@ -381,6 +382,24 @@ merge_include_chains (const char *sysroot, cpp_reader *pfile, int verbose) + } + fprintf (stderr, _("End of search list.\n")); + } ++ ++#ifdef ENABLE_POISON_SYSTEM_DIRECTORIES ++ if (flag_poison_system_directories) ++ { ++ struct cpp_dir *p; ++ ++ for (p = heads[QUOTE]; p; p = p->next) ++ { ++ if ((!strncmp (p->name, "/usr/include", 12)) ++ || (!strncmp (p->name, "/usr/local/include", 18)) ++ || (!strncmp (p->name, "/usr/X11R6/include", 18))) ++ warning (OPT_Wpoison_system_directories, ++ "include location \"%s\" is unsafe for " ++ "cross-compilation", ++ p->name); ++ } ++ } ++#endif + } + + /* Use given -I paths for #include "..." but not #include <...>, and +-- +2.8.2 + diff --git a/legacy/gcc6/090_all_pr55930-dependency-tracking.patch b/legacy/gcc6/090_all_pr55930-dependency-tracking.patch new file mode 100644 index 000000000..a8743e08c --- /dev/null +++ b/legacy/gcc6/090_all_pr55930-dependency-tracking.patch @@ -0,0 +1,18 @@ +libatomic build failure if configured with --disable-dependency-tracking +load_n.c:115:1: fatal error: opening dependency file .deps/load_1_.lo.Ppo: No such file or directory + +https://bugs.gentoo.org/463463 +http://gcc.gnu.org/PR55930 + +--- a/libatomic/Makefile.in ++++ b/libatomic/Makefile.in +@@ -298,7 +298,8 @@ PAT_N = $(word 2,$(PAT_SPLIT)) + PAT_S = $(word 3,$(PAT_SPLIT)) + IFUNC_DEF = -DIFUNC_ALT=$(PAT_S) + IFUNC_OPT = $(word $(PAT_S),$(IFUNC_OPTIONS)) +-M_DEPS = -MT $@ -MD -MP -MF $(DEPDIR)/$(@F).Ppo ++@AMDEP_TRUE@M_DEPS = -MT $@ -MD -MP -MF $(DEPDIR)/$(@F).Ppo ++@AMDEP_FALSE@M_DEPS = + M_SIZE = -DN=$(PAT_N) + M_IFUNC = $(if $(PAT_S),$(IFUNC_DEF) $(IFUNC_OPT)) + M_FILE = $(PAT_BASE)_n.c diff --git a/legacy/gcc6/201-cilkrts.patch b/legacy/gcc6/201-cilkrts.patch new file mode 100644 index 000000000..4aac10d6d --- /dev/null +++ b/legacy/gcc6/201-cilkrts.patch @@ -0,0 +1,59 @@ +From 594e3c1ab576daddeb86015efc8b1677020b1878 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <nsz@port70.net> +Date: Sat, 24 Oct 2015 20:39:30 +0000 +Subject: [PATCH 1/6] cilkrts + +--- + libcilkrts/runtime/os-unix.c | 22 +++++++--------------- + 1 file changed, 7 insertions(+), 15 deletions(-) + +diff --git a/libcilkrts/runtime/os-unix.c b/libcilkrts/runtime/os-unix.c +index cb582dd..e43d7d5 100644 +--- a/libcilkrts/runtime/os-unix.c ++++ b/libcilkrts/runtime/os-unix.c +@@ -51,6 +51,7 @@ + #if defined __linux__ + # include <sys/sysinfo.h> + # include <sys/syscall.h> ++# include <sched.h> + #elif defined __APPLE__ + # include <sys/sysctl.h> + // Uses sysconf(_SC_NPROCESSORS_ONLN) in verbose output +@@ -400,28 +401,19 @@ COMMON_SYSDEP void __cilkrts_sleep(void) + + COMMON_SYSDEP void __cilkrts_yield(void) + { +-#if __APPLE__ || __FreeBSD__ || __VXWORKS__ +- // On MacOS, call sched_yield to yield quantum. I'm not sure why we +- // don't do this on Linux also. +- sched_yield(); +-#elif defined(__DragonFly__) +- // On DragonFly BSD, call sched_yield to yield quantum. +- sched_yield(); +-#elif defined(__MIC__) ++#if defined(__MIC__) + // On MIC, pthread_yield() really trashes things. Arch's measurements + // showed that calling _mm_delay_32() (or doing nothing) was a better + // option. Delaying 1024 clock cycles is a reasonable compromise between + // giving up the processor and latency starting up when work becomes + // available + _mm_delay_32(1024); +-#elif defined(__ANDROID__) || (defined(__sun__) && defined(__svr4__)) +- // On Android and Solaris, call sched_yield to yield quantum. I'm not +- // sure why we don't do this on Linux also. +- sched_yield(); +-#else +- // On Linux, call pthread_yield (which in turn will call sched_yield) +- // to yield quantum. ++#elif defined(__sun__) && !defined(__svr4__) ++ // On old SunOS call pthread_yield to yield a quantum. + pthread_yield(); ++#else ++ // On other platforms call sched_yield to yield a quantum. ++ sched_yield(); + #endif + } + +-- +2.8.1 + diff --git a/legacy/gcc6/203-libgcc_s.patch b/legacy/gcc6/203-libgcc_s.patch new file mode 100644 index 000000000..c74351c71 --- /dev/null +++ b/legacy/gcc6/203-libgcc_s.patch @@ -0,0 +1,56 @@ +From 9e3eab51e518018d9d99b3123598b1e2322a6af3 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <nsz@port70.net> +Date: Sat, 24 Oct 2015 20:09:53 +0000 +Subject: [PATCH 3/6] libgcc_s + +--- + gcc/config/i386/i386.c | 4 ++-- + libgcc/config/i386/cpuinfo.c | 6 +++--- + libgcc/config/i386/t-linux | 2 +- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index 3d044e8..82523e1 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -40269,10 +40269,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget, + { + case IX86_BUILTIN_CPU_INIT: + { +- /* Make it call __cpu_indicator_init in libgcc. */ ++ /* Make it call __cpu_indicator_init_local in libgcc.a. */ + tree call_expr, fndecl, type; + type = build_function_type_list (integer_type_node, NULL_TREE); +- fndecl = build_fn_decl ("__cpu_indicator_init", type); ++ fndecl = build_fn_decl ("__cpu_indicator_init_local", type); + call_expr = build_call_expr (fndecl, 0); + return expand_expr (call_expr, target, mode, EXPAND_NORMAL); + } +diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c +index 8c2248d..6c82f15 100644 +--- a/libgcc/config/i386/cpuinfo.c ++++ b/libgcc/config/i386/cpuinfo.c +@@ -485,7 +485,7 @@ __cpu_indicator_init (void) + return 0; + } + +-#if defined SHARED && defined USE_ELF_SYMVER +-__asm__ (".symver __cpu_indicator_init, __cpu_indicator_init@GCC_4.8.0"); +-__asm__ (".symver __cpu_model, __cpu_model@GCC_4.8.0"); ++#ifndef SHARED ++int __cpu_indicator_init_local (void) ++ __attribute__ ((weak, alias ("__cpu_indicator_init"))); + #endif +diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux +index 11bb46e..4f47f7b 100644 +--- a/libgcc/config/i386/t-linux ++++ b/libgcc/config/i386/t-linux +@@ -3,4 +3,4 @@ + # t-slibgcc-elf-ver and t-linux + SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver + +-HOST_LIBGCC2_CFLAGS += -mlong-double-80 -DUSE_ELF_SYMVER ++HOST_LIBGCC2_CFLAGS += -mlong-double-80 +-- +2.8.1 + diff --git a/legacy/gcc6/204-linux_libc_has_function.patch b/legacy/gcc6/204-linux_libc_has_function.patch new file mode 100644 index 000000000..2dcedc3a7 --- /dev/null +++ b/legacy/gcc6/204-linux_libc_has_function.patch @@ -0,0 +1,25 @@ +From edec78452d693fb524daa9a6efd45c850b27b25c Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <nsz@port70.net> +Date: Fri, 6 Nov 2015 23:59:20 +0000 +Subject: [PATCH 4/6] linux_libc_has_function + +--- + gcc/config/linux.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gcc/config/linux.c b/gcc/config/linux.c +index 250296b..16c3768 100644 +--- a/gcc/config/linux.c ++++ b/gcc/config/linux.c +@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3. If not see + bool + linux_libc_has_function (enum function_class fn_class) + { +- if (OPTION_GLIBC) ++ if (OPTION_GLIBC || OPTION_MUSL) + return true; + if (OPTION_BIONIC) + if (fn_class == function_c94 +-- +2.8.1 + diff --git a/legacy/gcc6/205-nopie.patch b/legacy/gcc6/205-nopie.patch new file mode 100644 index 000000000..e3da94d10 --- /dev/null +++ b/legacy/gcc6/205-nopie.patch @@ -0,0 +1,75 @@ +From b6015aca9c9cc83739fd0ed637a835119b2c4e34 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <nsz@port70.net> +Date: Sat, 7 Nov 2015 02:08:05 +0000 +Subject: [PATCH 5/6] nopie + +--- + gcc/configure | 27 +++++++++++++++++++++++++++ + gcc/configure.ac | 13 +++++++++++++ + 2 files changed, 40 insertions(+) + +diff --git a/gcc/configure b/gcc/configure +index 1c6e340..7e8b5d6 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -29390,6 +29390,33 @@ fi + $as_echo "$gcc_cv_no_pie" >&6; } + if test "$gcc_cv_no_pie" = "yes"; then + NO_PIE_FLAG="-no-pie" ++else ++ # Check if -nopie works. ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -nopie option" >&5 ++$as_echo_n "checking for -nopie option... " >&6; } ++if test "${gcc_cv_nopie+set}" = set; then : ++ $as_echo_n "(cached) " >&6 ++else ++ saved_LDFLAGS="$LDFLAGS" ++ LDFLAGS="$LDFLAGS -nopie" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++int main(void) {return 0;} ++_ACEOF ++if ac_fn_cxx_try_link "$LINENO"; then : ++ gcc_cv_nopie=yes ++else ++ gcc_cv_nopie=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ LDFLAGS="$saved_LDFLAGS" ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_nopie" >&5 ++$as_echo "$gcc_cv_nopie" >&6; } ++ if test "$gcc_cv_nopie" = "yes"; then ++ NO_PIE_FLAG="-nopie" ++ fi + fi + + +diff --git a/gcc/configure.ac b/gcc/configure.ac +index 6c1dcd9..0ca7647 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -6098,6 +6098,19 @@ AC_CACHE_CHECK([for -no-pie option], + LDFLAGS="$saved_LDFLAGS"]) + if test "$gcc_cv_no_pie" = "yes"; then + NO_PIE_FLAG="-no-pie" ++else ++ # Check if -nopie works. ++ AC_CACHE_CHECK([for -nopie option], ++ [gcc_cv_nopie], ++ [saved_LDFLAGS="$LDFLAGS" ++ LDFLAGS="$LDFLAGS -nopie" ++ AC_LINK_IFELSE([int main(void) {return 0;}], ++ [gcc_cv_nopie=yes], ++ [gcc_cv_nopie=no]) ++ LDFLAGS="$saved_LDFLAGS"]) ++ if test "$gcc_cv_nopie" = "yes"; then ++ NO_PIE_FLAG="-nopie" ++ fi + fi + AC_SUBST([NO_PIE_FLAG]) + +-- +2.8.1 + diff --git a/legacy/gcc6/207-static-pie.patch b/legacy/gcc6/207-static-pie.patch new file mode 100644 index 000000000..9355c584b --- /dev/null +++ b/legacy/gcc6/207-static-pie.patch @@ -0,0 +1,40 @@ +diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h +index b0bf40a..d4b56fe 100644 +--- a/gcc/config/gnu-user.h ++++ b/gcc/config/gnu-user.h +@@ -51,10 +51,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #if defined HAVE_LD_PIE + #define GNU_USER_TARGET_STARTFILE_SPEC \ + "%{!shared: %{pg|p|profile:gcrt1.o%s;: \ +- %{" PIE_SPEC ":Scrt1.o%s} %{" NO_PIE_SPEC ":crt1.o%s}}} \ +- crti.o%s %{static:crtbeginT.o%s;: %{shared:crtbeginS.o%s} \ ++ %{" PIE_SPEC ":%{static:rcrt1.o%s;:Scrt1.o%s}} %{" NO_PIE_SPEC ":crt1.o%s}}} \ ++ crti.o%s %{shared:crtbeginS.o%s;: \ + %{" PIE_SPEC ":crtbeginS.o%s} \ +- %{" NO_PIE_SPEC ":crtbegin.o%s}} \ ++ %{" NO_PIE_SPEC ":%{static:crtbeginT.o%s;:crtbegin.o%s}}} \ + %{fvtable-verify=none:%s; \ + fvtable-verify=preinit:vtv_start_preinit.o%s; \ + fvtable-verify=std:vtv_start.o%s} \ +diff --git a/gcc/gcc.c b/gcc/gcc.c +index 0208d61..731564e 100644 +--- a/gcc/gcc.c ++++ b/gcc/gcc.c +@@ -870,7 +870,7 @@ proper position among the other output files. */ + #endif + + #ifdef ENABLE_DEFAULT_PIE +-#define NO_PIE_SPEC "no-pie|static" ++#define NO_PIE_SPEC "no-pie" + #define PIE_SPEC NO_PIE_SPEC "|r|shared:;" + #define NO_FPIE1_SPEC "fno-pie" + #define FPIE1_SPEC NO_FPIE1_SPEC ":;" +@@ -916,7 +916,7 @@ proper position among the other output files. */ + #ifndef LINK_PIE_SPEC + #ifdef HAVE_LD_PIE + #ifndef LD_PIE_SPEC +-#define LD_PIE_SPEC "-pie" ++#define LD_PIE_SPEC "-pie %{static:--no-dynamic-linker -Bsymbolic}" + #endif + #else + #define LD_PIE_SPEC "" diff --git a/legacy/gcc6/300-main-gcc-add-musl-s390x-dynamic-linker.patch b/legacy/gcc6/300-main-gcc-add-musl-s390x-dynamic-linker.patch new file mode 100644 index 000000000..241957871 --- /dev/null +++ b/legacy/gcc6/300-main-gcc-add-musl-s390x-dynamic-linker.patch @@ -0,0 +1,32 @@ +From be841c16dd544553c67faac79bd4cc3cd10a1dc0 Mon Sep 17 00:00:00 2001 +From: "Tuan M. Hoang" <tmhoang@flatglobe.org> +Date: Mon, 21 Nov 2016 01:42:16 +0700 +Subject: [PATCH] main/gcc: add musl s390x dynamic linker + +--- + gcc/config/s390/linux.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h +index 1e3ed35..a244214 100644 +--- a/gcc/config/s390/linux.h ++++ b/gcc/config/s390/linux.h +@@ -63,6 +63,15 @@ along with GCC; see the file COPYING3. If not see + #define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1" + #define GLIBC_DYNAMIC_LINKER64 "/lib/ld64.so.1" + ++#undef MUSL_DYNAMIC_LINKER ++#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-s390x.so.1" ++#undef MUSL_DYNAMIC_LINKER32 ++#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-s390x.so.1" ++#undef MUSL_DYNAMIC_LINKER64 ++#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-s390x.so.1" ++#undef MUSL_DYNAMIC_LINKERX32 ++#define MUSL_DYNAMIC_LINKERX32 "/lib/ld-musl-s390x.so.1" ++ + #undef LINK_SPEC + #define LINK_SPEC \ + "%{m31:-m elf_s390}%{m64:-m elf64_s390} --as-needed \ +-- +2.10.2 + diff --git a/legacy/gcc6/310-build-gcj-s390x.patch b/legacy/gcc6/310-build-gcj-s390x.patch new file mode 100644 index 000000000..1e522ee15 --- /dev/null +++ b/legacy/gcc6/310-build-gcj-s390x.patch @@ -0,0 +1,28 @@ +From 697a7ba791fce2ffab2ed723d909a89684019e3d Mon Sep 17 00:00:00 2001 +From: "Tuan M. Hoang" <tmhoang@flatglobe.org> +Date: Sun, 19 Feb 2017 17:03:33 +0000 +Subject: [PATCH] main/gcc : when building gcc-java on s390x, libgcj.so + complains about undefined reference to __data_start. Using + SEARCH_FOR_DATA_START instead solved it. Credit to Andrew Haley at RedHat. + +--- + boehm-gc/include/private/gcconfig.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/boehm-gc/include/private/gcconfig.h b/boehm-gc/include/private/gcconfig.h +index 4ca6a80..a15fff6 100644 +--- a/boehm-gc/include/private/gcconfig.h ++++ b/boehm-gc/include/private/gcconfig.h +@@ -1837,8 +1837,7 @@ + # define OS_TYPE "LINUX" + # define LINUX_STACKBOTTOM + # define DYNAMIC_LOADING +- extern int __data_start[]; +-# define DATASTART ((ptr_t)(__data_start)) ++# define SEARCH_FOR_DATA_START + extern int _end[]; + # define DATAEND (_end) + # define CACHE_LINE_SIZE 256 +-- +2.11.1 + diff --git a/legacy/gcc6/320-libffi-gnulinux.patch b/legacy/gcc6/320-libffi-gnulinux.patch new file mode 100644 index 000000000..b3b4fc931 --- /dev/null +++ b/legacy/gcc6/320-libffi-gnulinux.patch @@ -0,0 +1,13 @@ +diff --git a/libffi/closures.c.orig b/libffi/closures.c +index 721ff00..22a699c 100644 +--- a/libffi/src/closures.c.orig ++++ b/libffi/src/closures.c +@@ -34,7 +34,7 @@ + #include <ffi_common.h> + + #if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE +-# if __gnu_linux__ && !defined(__ANDROID__) ++# if __linux__ && !defined(__ANDROID__) + /* This macro indicates it may be forbidden to map anonymous memory + with both write and execute permission. Code compiled when this + option is defined will attempt to map such pages once, but if it diff --git a/legacy/gcc6/330-gccgo-link-to-ucontext.patch b/legacy/gcc6/330-gccgo-link-to-ucontext.patch new file mode 100644 index 000000000..8aa60ca54 --- /dev/null +++ b/legacy/gcc6/330-gccgo-link-to-ucontext.patch @@ -0,0 +1,11 @@ +--- gcc-6.4.0/Makefile.in.old 2018-06-21 22:16:35.167781541 -0500 ++++ gcc-6.4.0/Makefile.in 2018-06-22 00:36:13.849486086 -0500 +@@ -41332,7 +41332,7 @@ + esac; \ + module_srcdir=libgo; \ + rm -f no-such-file || : ; \ +- CONFIG_SITE=no-such-file $(SHELL) \ ++ CONFIG_SITE=no-such-file LIBS="-lucontext $$LIBS" $(SHELL) \ + $$s/$$module_srcdir/configure \ + --srcdir=$${topdir}/$$module_srcdir \ + $(TARGET_CONFIGARGS) --build=${build_alias} --host=${target_alias} \ diff --git a/legacy/gcc6/331-gccgo-use-real-off_t-type.patch b/legacy/gcc6/331-gccgo-use-real-off_t-type.patch new file mode 100644 index 000000000..1c8c43e9e --- /dev/null +++ b/legacy/gcc6/331-gccgo-use-real-off_t-type.patch @@ -0,0 +1,30 @@ +--- gcc-6.4.0/libgo/go/syscall/libcall_linux.go.old 2016-02-03 15:58:02.419872000 -0600 ++++ gcc-6.4.0/libgo/go/syscall/libcall_linux.go 2018-06-22 00:56:31.478280552 -0500 +@@ -355,19 +355,19 @@ + //sys Setxattr(path string, attr string, data []byte, flags int) (err error) + //setxattr(path *byte, name *byte, value *byte, size Size_t, flags _C_int) _C_int + +-//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error) +-//splice(rfd _C_int, roff *_loff_t, wfd _C_int, woff *_loff_t, len Size_t, flags _C_uint) Ssize_t ++//sys splice(rfd int, roff *_off_t, wfd int, woff *_off_t, len int, flags int) (n int64, err error) ++//splice(rfd _C_int, roff *_off_t, wfd _C_int, woff *_off_t, len Size_t, flags _C_uint) Ssize_t + func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { +- var lroff _loff_t +- var plroff *_loff_t ++ var lroff _off_t ++ var plroff *_off_t + if roff != nil { +- lroff = _loff_t(*roff) ++ lroff = _off_t(*roff) + plroff = &lroff + } +- var lwoff _loff_t +- var plwoff *_loff_t ++ var lwoff _off_t ++ var plwoff *_off_t + if woff != nil { +- lwoff = _loff_t(*woff) ++ lwoff = _off_t(*woff) + plwoff = &lwoff + } + n, err = splice(rfd, plroff, wfd, plwoff, len, flags) diff --git a/legacy/gcc6/332-gccgo-remove-ustat.patch b/legacy/gcc6/332-gccgo-remove-ustat.patch new file mode 100644 index 000000000..90aa65ad7 --- /dev/null +++ b/legacy/gcc6/332-gccgo-remove-ustat.patch @@ -0,0 +1,190 @@ +From bdead75ea02fa852a559f35b41453df0c47c9a66 Mon Sep 17 00:00:00 2001 +From: Ian Lance Taylor <iant@golang.org> +Date: Fri, 22 Jun 2018 06:24:48 -0700 +Subject: [PATCH] syscall: remove Ustat + +glibc 2.28 removes ustat.h and the ustat function entirely, which +breaks syscall.Ustat. + +Updates golang/go#25990 + +Change-Id: I430802c86389a02cb4a0cd6caff36fa542d98f2f +Reviewed-on: https://go-review.googlesource.com/120535 +Reviewed-by: Than McIntosh <thanm@google.com> +--- + libgo/config.h.in | 3 --- + libgo/configure | 33 --------------------------------- + libgo/configure.ac | 18 ------------------ + libgo/go/syscall/libcall_linux_ustat.go | 12 ------------ + libgo/mksysinfo.sh | 14 -------------- + libgo/sysinfo.c | 3 --- + 6 files changed, 83 deletions(-) + delete mode 100644 libgo/go/syscall/libcall_linux_ustat.go + +diff --git a/libgo/config.h.in b/libgo/config.h.in +index 57560cd0..de57d0cc 100644 +--- a/libgo/config.h.in ++++ b/libgo/config.h.in +@@ -343,9 +343,6 @@ + /* Define to 1 if you have the `unshare' function. */ + #undef HAVE_UNSHARE + +-/* Define to 1 if you have the <ustat.h> header file and it works. */ +-#undef HAVE_USTAT_H +- + /* Define to 1 if you have the `utimensat' function. */ + #undef HAVE_UTIMENSAT + +diff --git a/libgo/configure b/libgo/configure +index 66942eda..7166f940 100755 +--- a/libgo/configure ++++ b/libgo/configure +@@ -14760,39 +14760,6 @@ fi + done + + +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether <ustat.h> can be used" >&5 +-$as_echo_n "checking whether <ustat.h> can be used... " >&6; } +-if test "${libgo_cv_c_ustat_h+set}" = set; then : +- $as_echo_n "(cached) " >&6 +-else +- CFLAGS_hold=$CFLAGS +-CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE $OSCFLAGS" +-cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +- +-#include <sys/types.h> +-#ifdef HAVE_LINUX_FILTER_H +-#include <linux/filter.h> +-#endif +-#include <ustat.h> +- +-_ACEOF +-if ac_fn_c_try_compile "$LINENO"; then : +- libgo_cv_c_ustat_h=yes +-else +- libgo_cv_c_ustat_h=no +-fi +-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +-CFLAGS=$CFLAGS_hold +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_ustat_h" >&5 +-$as_echo "$libgo_cv_c_ustat_h" >&6; } +-if test $libgo_cv_c_ustat_h = yes; then +- +-$as_echo "#define HAVE_USTAT_H 1" >>confdefs.h +- +-fi +- + if test "$ac_cv_header_sys_mman_h" = yes; then + HAVE_SYS_MMAN_H_TRUE= + HAVE_SYS_MMAN_H_FALSE='#' +diff --git a/libgo/configure.ac b/libgo/configure.ac +index 3cee2c0f..1c192752 100644 +--- a/libgo/configure.ac ++++ b/libgo/configure.ac +@@ -537,24 +537,6 @@ AC_CHECK_HEADERS([linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h + #endif + ]) + +-AC_CACHE_CHECK([whether <ustat.h> can be used], +-[libgo_cv_c_ustat_h], +-[CFLAGS_hold=$CFLAGS +-CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE $OSCFLAGS" +-AC_COMPILE_IFELSE( +-[AC_LANG_SOURCE([ +-#include <sys/types.h> +-#ifdef HAVE_LINUX_FILTER_H +-#include <linux/filter.h> +-#endif +-#include <ustat.h> +-])], [libgo_cv_c_ustat_h=yes], [libgo_cv_c_ustat_h=no]) +-CFLAGS=$CFLAGS_hold]) +-if test $libgo_cv_c_ustat_h = yes; then +- AC_DEFINE(HAVE_USTAT_H, 1, +- [Define to 1 if you have the <ustat.h> header file and it works.]) +-fi +- + AM_CONDITIONAL(HAVE_SYS_MMAN_H, test "$ac_cv_header_sys_mman_h" = yes) + + AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv unsetenv dl_iterate_phdr) +diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh +index 92ecb479..48bc71db 100755 +--- a/libgo/mksysinfo.sh ++++ b/libgo/mksysinfo.sh +@@ -1164,20 +1164,6 @@ grep '^type _sysinfo ' gen-sysinfo.go | \ + -e 's/mem_unit/Unit/' \ + >> ${OUT} + +-# The ustat struct. +-grep '^type _ustat ' gen-sysinfo.go | \ +- sed -e 's/_ustat/Ustat_t/' \ +- -e 's/f_tfree/Tfree/' \ +- -e 's/f_tinode/Tinoe/' \ +- -e 's/f_fname/Fname/' \ +- -e 's/f_fpack/Fpack/' \ +- >> ${OUT} +-# Force it to be defined, as on some older GNU/Linux systems the +-# header file fails when using with <linux/filter.h>. +-if ! grep 'type _ustat ' gen-sysinfo.go >/dev/null 2>&1; then +- echo 'type Ustat_t struct { Tfree int32; Tinoe uint64; Fname [5+1]int8; Fpack [5+1]int8; }' >> ${OUT} +-fi +- + # The utimbuf struct. + grep '^type _utimbuf ' gen-sysinfo.go | \ + sed -e 's/_utimbuf/Utimbuf/' \ +--- gcc-6.4.0/libgo/Makefile.am.old 2016-02-03 15:58:02.419872000 -0600 ++++ gcc-6.4.0/libgo/Makefile.am 2018-06-23 02:55:45.772611885 -0500 +@@ -1,4 +1,3 @@ +-# Makefile.am -- Go library Makefile. + + # Copyright 2009 The Go Authors. All rights reserved. + # Use of this source code is governed by a BSD-style +@@ -1989,17 +1988,6 @@ + syscall_lsf_file = + endif + +-# GNU/Linux specific ustat support. +-if LIBGO_IS_LINUX +-if LIBGO_IS_ARM64 +-syscall_ustat_file = +-else +-syscall_ustat_file = go/syscall/libcall_linux_ustat.go +-endif +-else +-syscall_ustat_file = +-endif +- + # GNU/Linux specific utimesnano support. + if LIBGO_IS_LINUX + syscall_utimesnano_file = go/syscall/libcall_linux_utimesnano.go +@@ -2051,7 +2039,6 @@ + $(syscall_uname_file) \ + $(syscall_netlink_file) \ + $(syscall_lsf_file) \ +- $(syscall_ustat_file) \ + $(syscall_utimesnano_file) \ + $(GO_LIBCALL_OS_FILE) \ + $(GO_LIBCALL_OS_ARCH_FILE) \ +--- gcc-6.4.0/libgo/Makefile.in.old 2016-02-03 15:58:02.419872000 -0600 ++++ gcc-6.4.0/libgo/Makefile.in 2018-06-23 02:56:04.842611681 -0500 +@@ -2080,11 +2080,6 @@ + + # GNU/Linux specific socket filters. + @LIBGO_IS_LINUX_TRUE@syscall_lsf_file = go/syscall/lsf_linux.go +-@LIBGO_IS_ARM64_FALSE@@LIBGO_IS_LINUX_TRUE@syscall_ustat_file = go/syscall/libcall_linux_ustat.go +- +-# GNU/Linux specific ustat support. +-@LIBGO_IS_ARM64_TRUE@@LIBGO_IS_LINUX_TRUE@syscall_ustat_file = +-@LIBGO_IS_LINUX_FALSE@syscall_ustat_file = + @LIBGO_IS_LINUX_FALSE@syscall_utimesnano_file = go/syscall/libcall_posix_utimesnano.go + + # GNU/Linux specific utimesnano support. +@@ -2122,7 +2117,6 @@ + $(syscall_uname_file) \ + $(syscall_netlink_file) \ + $(syscall_lsf_file) \ +- $(syscall_ustat_file) \ + $(syscall_utimesnano_file) \ + $(GO_LIBCALL_OS_FILE) \ + $(GO_LIBCALL_OS_ARCH_FILE) \ diff --git a/legacy/gcc6/APKBUILD b/legacy/gcc6/APKBUILD new file mode 100644 index 000000000..6e6c8e76d --- /dev/null +++ b/legacy/gcc6/APKBUILD @@ -0,0 +1,667 @@ +# Maintainer: Adelie Platform Group <adelie-devel@lists.adelielinux.org> +_major=6 +pkgname=gcc$_major +pkgver=6.4.0 +_ecjver=4.9 +[ "$BOOTSTRAP" = "nolibc" ] && pkgname="gcc-pass2" +[ "$CBUILD" != "$CHOST" ] && _cross="-$CARCH" || _cross="" +[ "$CHOST" != "$CTARGET" ] && _target="-$CTARGET_ARCH" || _target="" + +pkgname="$pkgname$_target" +pkgrel=11 +pkgdesc="The GNU Compiler Collection" +url="https://gcc.gnu.org" +arch="all" +license="GPL-3.0+ AND LGPL-2.1+" +_gccrel=$pkgver-r$pkgrel +depends="binutils$_target isl" +makedepends_build="gcc$_cross g++$_cross bison flex texinfo zip gmp-dev mpfr-dev mpc1-dev zlib-dev" +makedepends_host="linux-headers gmp-dev mpfr-dev mpc1-dev isl-dev zlib-dev libucontext-dev" +subpackages=" " +[ "$CHOST" = "$CTARGET" ] && subpackages="gcc$_major-doc$_target gcc$_major-lang$_target" +replaces="libstdc++ binutils" +options="$options !check !dbg strip toolchain" + +: ${LANG_CXX:=true} +: ${LANG_OBJC:=true} +: ${LANG_JAVA:=true} +: ${LANG_GO:=true} +: ${LANG_FORTRAN:=true} +: ${LANG_ADA:=false} + +LIBGOMP=true +LIBGCC=true +LIBATOMIC=true +LIBITM=true + +if [ "$CHOST" != "$CTARGET" ]; then + if [ "$BOOTSTRAP" = nolibc ]; then + LANG_CXX=false + LANG_ADA=false + LIBGCC=false + _builddir="$srcdir/build-cross-pass2" + else + _builddir="$srcdir/build-cross-final" + fi + LANG_OBJC=false + LANG_JAVA=false + LANG_GO=false + LANG_FORTRAN=false + LIBGOMP=false + LIBATOMIC=false + LIBITM=false + + # reset target flags (should be set in crosscreate abuild) + # fixup flags. seems gcc treats CPPFLAGS as global without + # _FOR_xxx variants. wrap it in CFLAGS and CXXFLAGS. + export CFLAGS="$CPPFLAGS $CFLAGS" + export CXXFLAGS="$CPPFLAGS $CXXFLAGS" + unset CPPFLAGS + export CFLAGS_FOR_TARGET=" " + export CXXFLAGS_FOR_TARGET=" " + export LDFLAGS_FOR_TARGET=" " + + STRIP_FOR_TARGET="$CTARGET-strip" +elif [ "$CBUILD" != "$CHOST" ]; then + # fixup flags. seems gcc treats CPPFLAGS as global without + # _FOR_xxx variants. wrap it in CFLAGS and CXXFLAGS. + export CFLAGS="$CPPFLAGS $CFLAGS" + export CXXFLAGS="$CPPFLAGS $CXXFLAGS" + unset CPPFLAGS + + # reset flags and cc for build + export CC_FOR_BUILD="gcc" + export CXX_FOR_BUILD="g++" + export CFLAGS_FOR_BUILD=" " + export CXXFLAGS_FOR_BUILD=" " + export LDFLAGS_FOR_BUILD=" " + export CFLAGS_FOR_TARGET=" " + export CXXFLAGS_FOR_TARGET=" " + export LDFLAGS_FOR_TARGET=" " + + # Languages that do not need bootstrapping + LANG_OBJC=false + LANG_JAVA=false + LANG_GO=false + LANG_FORTRAN=false + + STRIP_FOR_TARGET=${CROSS_COMPILE}strip + _builddir="$srcdir/build-cross-native" +else + STRIP_FOR_TARGET=${CROSS_COMPILE}strip + _builddir="$srcdir/build" +fi + +# libitm has TEXTRELs in ARM build, so disable for now +# gcc itself has TEXTRELs in m68k; until this is fixed, we need it +case "$CTARGET_ARCH" in +arm*) LIBITM=false ;; +m68k) options="$options textrels" ;; +esac + +# Fortran uses libquadmath if toolchain has __float128 +# currently on x86, x86_64 and ia64 +LIBQUADMATH=$LANG_FORTRAN +case "$CTARGET_ARCH" in +pmmx | x86 | x86_64) LIBQUADMATH=$LANG_FORTRAN ;; +*) LIBQUADMATH=false ;; +esac + +# libatomic is a dependency for openvswitch +$LIBATOMIC && subpackages="$subpackages libatomic$_major::$CTARGET_ARCH" +$LIBGCC && subpackages="$subpackages libgcc$_major::$CTARGET_ARCH" +$LIBQUADMATH && subpackages="$subpackages libquadmath$_major::$CTARGET_ARCH" +if $LIBGOMP; then + depends="$depends libgomp=$_gccrel" + subpackages="$subpackages libgomp$_major::$CTARGET_ARCH" +fi + +_languages=c +if $LANG_CXX; then + subpackages="$subpackages libstdc++:libcxx:$CTARGET_ARCH g++$_target:gpp" + _languages="$_languages,c++" +fi +if $LANG_OBJC; then + subpackages="$subpackages libobjc::$CTARGET_ARCH gcc-objc$_target:objc" + _languages="$_languages,objc" +fi +if $LANG_JAVA; then + subpackages="$subpackages libgcj::$CTARGET_ARCH gcc-java$_target:java" + _languages="$_languages,java" +fi +if $LANG_GO; then + subpackages="$subpackages libgo::$CTARGET_ARCH gcc-go$_target:go" + _languages="$_languages,go" +fi +if $LANG_FORTRAN; then + subpackages="$subpackages libgfortran::$CTARGET_ARCH gfortran$_target:gfortran" + _languages="$_languages,fortran" +fi +if $LANG_ADA; then + subpackages="$subpackages libgnat::$CTARGET_ARCH gcc-gnat$_target:gnat" + _languages="$_languages,ada" + makedepends_build="$makedepends_build gcc-gnat gcc-gnat$_cross" +fi +makedepends="$makedepends_build $makedepends_host" + +source="https://ftp.gnu.org/gnu/gcc/gcc-$pkgver/gcc-$pkgver.tar.xz + https://sourceware.org/pub/java/ecj-$_ecjver.jar + + 001_all_default-ssp-strong.patch + 002_all_default-relro.patch + 003_all_default-fortify-source.patch + 005_all_default-as-needed.patch + 011_all_default-warn-format-security.patch + 012_all_default-warn-trampolines.patch + 020_all_msgfmt-libstdc++-link.patch + 050_all_libiberty-asprintf.patch + 051_all_libiberty-pic.patch + 053_all_libitm-no-fortify-source.patch + 067_all_gcc-poison-system-directories.patch + 090_all_pr55930-dependency-tracking.patch + + 201-cilkrts.patch + 203-libgcc_s.patch + 204-linux_libc_has_function.patch + 205-nopie.patch + 207-static-pie.patch + + libgcc-always-build-gcceh.a.patch + gcc-4.9-musl-fortify.patch + gcc-6.1-musl-libssp.patch + boehm-gc-musl.patch + gcc-pure64.patch + fix-gcj-stdgnu14-link.patch + fix-gcj-musl.patch + fix-gcj-iconv-musl.patch + + gcc-4.8-build-args.patch + fix-cxxflags-passing.patch + ada-fixes.patch + ada-shared.patch + ada-musl.patch + ada-aarch64-multiarch.patch + + 300-main-gcc-add-musl-s390x-dynamic-linker.patch + 310-build-gcj-s390x.patch + 320-libffi-gnulinux.patch + 330-gccgo-link-to-ucontext.patch + 331-gccgo-use-real-off_t-type.patch + 332-gccgo-remove-ustat.patch + libgo-musl-1.2.3.patch + + fix-rs6000-pie.patch + add-classic_table-support.patch + lra-pentium.patch + + gcc-5.4.0-locale.patch + isl-fix.patch + " + +# we build out-of-tree +_gccdir="$srcdir"/gcc-$pkgver +_gcclibdir=/usr/lib/gcc/${CTARGET}/$pkgver +_gcclibexec=/usr/libexec/gcc/${CTARGET}/$pkgver + +prepare() { + cd "$_gccdir" + + _err= + for i in $source; do + case "$i" in + *.patch) + msg "Applying $i" + patch -p1 -F3 -i "$srcdir"/$i || _err="$_err $i" + ;; + esac + done + + if [ -n "$_err" ]; then + error "The following patches failed:" + for i in $_err; do + echo " $i" + done + return 1 + fi + + # see http://gcc.gnu.org/ml/java/2008-04/msg00027.html + mv "$srcdir"/ecj-*.jar ecj.jar + + echo ${pkgver} > gcc/BASE-VER + echo "UNSUPPORTED=1" > libcilkrts/configure.tgt + rm libgo/go/syscall/libcall_linux_ustat.go +} + +build() { + local _arch_configure= + local _libc_configure= + local _cross_configure= + local _bootstrap_configure= + local _hash_style=gnu + local _symvers= + + cd "$_gccdir" + + case "$CTARGET" in + aarch64-*-*-*) _arch_configure="--with-arch=armv8-a --with-abi=lp64 --enable-fix-cortex-a53-835769 --enable-fix-cortex-a53-843419";; + armv5-*-*-*eabi) _arch_configure="--with-arch=armv5te --with-tune=arm926ej-s --with-float=soft --with-abi=aapcs-linux";; + armv6-*-*-*eabihf) _arch_configure="--with-arch=armv6zk --with-tune=arm1176jzf-s --with-fpu=vfp --with-float=hard --with-abi=aapcs-linux";; + armv7-*-*-*eabihf) _arch_configure="--with-arch=armv7-a --with-tune=generic-armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-abi=aapcs-linux --with-mode=thumb";; + m68k-*-*-*) _arch_configure="--with-arch=68020 --with-tune=68020-40";; + mipsel-*-*-*) _arch_configure="--with-arch-32=mips2 --with-tune-32=mips32 --with-fp-32=32 --with-mips-plt --with-float=hard --with-abi=32";; + mips-*-*-*) _arch_configure="--with-arch=mips3 --with-mips-plt --with-abi=32"; _hash_style="sysv";; + mips32el-*-*-*) _arch_configure="--with-arch=mips32 --with-mips-plt --with-abi=32"; _hash_style="sysv";; + powerpc-*-*-*) _arch_configure="--enable-secureplt --enable-decimal-float=no";; + powerpc64*-*-*-*) _arch_configure="--with-abi=elfv2 --enable-secureplt --enable-decimal-float=no";; + powerpc64le*-*-*-*) _arch_configure="--with-abi=elfv2 --enable-secureplt --enable-decimal-float=no";; + i486-*-*-*) _arch_configure="--with-arch=i486 --with-tune=generic --enable-cld";; + i586-*-*-*) _arch_configure="--with-arch=i586 --with-tune=pentium2 --enable-cld --enable-mmx";; + pentium3-*-*-*) _arch_configure="--with-arch=pentium3 --with-tune=pentium-m";; + s390x-*-*-*) _arch_configure="--with-arch=z196 --with-tune=zEC12 --with-zarch --with-long-double-128 --enable-decimal-float";; + esac + + case "$CTARGET_LIBC" in + musl) + # musl does not support mudflap, or libsanitizer + # libmpx uses secure_getenv and struct _libc_fpstate not present in musl + _libc_configure="--disable-libmpx --disable-libmudflap --disable-libsanitizer" + _symvers="--disable-symvers" + export libat_cv_have_ifunc=no + export ac_cv_type_off64_t=no + ;; + esac + + [ "$CBUILD" != "$CHOST" ] && _cross_configure="--disable-bootstrap" + [ "$CHOST" != "$CTARGET" ] && _cross_configure="--disable-bootstrap --with-sysroot=$CBUILDROOT" + + case "$BOOTSTRAP" in + nolibc) _bootstrap_configure="--with-newlib --disable-shared --enable-threads=no" ;; + *) _bootstrap_configure="--enable-shared --enable-threads --enable-tls" ;; + esac + + $LIBGOMP || _bootstrap_configure="$_bootstrap_configure --disable-libgomp" + $LIBATOMIC || _bootstrap_configure="$_bootstrap_configure --disable-libatomic" + $LIBITM || _bootstrap_configure="$_bootstrap_configure --disable-libitm" + $LIBQUADMATH || _arch_configure="$_arch_configure --disable-libquadmath" + + msg "Building the following:" + echo "" + echo " CBUILD=$CBUILD" + echo " CHOST=$CHOST" + echo " CTARGET=$CTARGET" + echo " CTARGET_ARCH=$CTARGET_ARCH" + echo " CTARGET_LIBC=$CTARGET_LIBC" + echo " languages=$_languages" + echo " arch_configure=$_arch_configure" + echo " libc_configure=$_libc_configure" + echo " cross_configure=$_cross_configure" + echo " bootstrap_configure=$_bootstrap_configure" + echo " hash_style=$_hash_style" + echo "" + + mkdir -p "$_builddir" + cd "$_builddir" + "$_gccdir"/configure --prefix=/usr \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --build=${CBUILD} \ + --host=${CHOST} \ + --target=${CTARGET} \ + --with-pkgversion="Adelie ${pkgver}" \ + --with-bugurl="http://bts.adelielinux.org/" \ + --enable-checking=release \ + --disable-fixed-point \ + --disable-libstdcxx-pch \ + --disable-multilib \ + --disable-werror \ + $_symvers \ + --enable-__cxa_atexit \ + --enable-default-pie \ + --enable-cloog-backend \ + --enable-languages=$_languages \ + $_arch_configure \ + $_libc_configure \ + $_cross_configure \ + $_bootstrap_configure \ + --with-system-zlib \ + --with-linker-hash-style=$_hash_style + make +} + +check() { + cd "$_builddir" + make check +} + +package() { + cd "$_builddir" + make -j1 DESTDIR="${pkgdir}" install + + ln -s gcc "$pkgdir"/usr/bin/cc + + # we dont support gcj -static + # and saving 35MB is not bad. + find "$pkgdir" -name libgcj.a -o -name libgtkpeer.a \ + -o -name libgjsmalsa.a -o -name libgcj-tools.a \ + -o -name libjvm.a -o -name libgij.a -o -name libgcj_bc.a \ + -o -name libjavamath.a \ + | xargs rm -f + + # strip debug info from some static libs + ${STRIP_FOR_TARGET} -g `find "$pkgdir" \( -name libgfortran.a -o -name libobjc.a -o -name libgomp.a \ + -o -name libmudflap.a -o -name libmudflapth.a \ + -o -name libgcc.a -o -name libgcov.a -o -name libquadmath.a \ + -o -name libitm.a -o -name libgo.a -o -name libcaf\*.a \ + -o -name libatomic.a -o -name libasan.a -o -name libtsan.a \) \ + -a -type f` + + if $LANG_JAVA; then + sed -i -e 's/lib: /&%{static:%eJava programs cannot be linked statically}/' \ + "$pkgdir"/usr/lib/libgcj.spec + fi + + if $LIBGOMP; then + mv "$pkgdir"/usr/lib/libgomp.spec "$pkgdir"/$_gcclibdir + fi + if $LIBITM; then + mv "$pkgdir"/usr/lib/libitm.spec "$pkgdir"/$_gcclibdir + fi + + # remove ffi + rm -f "$pkgdir"/usr/lib/libffi* "$pkgdir"/usr/share/man/man3/ffi* + find "$pkgdir" -name 'ffi*.h' | xargs rm -f + + local gdblib=${_target:+$CTARGET/}lib + for i in $(find "$pkgdir"/usr/$gdblib/ -type f -maxdepth 1 -name "*-gdb.py" ); do + mkdir -p "$pkgdir"/usr/share/gdb/python/auto-load/usr/$gdblib + mv "$i" "$pkgdir"/usr/share/gdb/python/auto-load/usr/$gdblib/ + done + + # move ada runtime libs + if $LANG_ADA; then + for i in $(find "$pkgdir"/$_gcclibdir/adalib/ -type f -maxdepth 1 -name "libgna*.so"); do + mv "$i" "$pkgdir"/usr/lib/ + ln -s ../../../../${i##*/} $i + done + fi + + if [ "$CHOST" != "$CTARGET" ]; then + # cross-gcc: remove any files that would conflict with the + # native gcc package + rm -rf "$pkgdir"/usr/bin/cc "$pkgdir"/usr/include "$pkgdir"/usr/share + # libcc1 does not depend on target, don't ship it + rm -rf "$pkgdir"/usr/lib/libcc1.so* + + # fixup gcc library symlinks to be linker scripts so + # linker finds the libs from relocated sysroot + for so in "$pkgdir"/usr/$CTARGET/lib/*.so; do + if [ -h "$so" ]; then + local _real=$(basename $(readlink "$so")) + rm -f "$so" + echo "GROUP ($_real)" > "$so" + fi + done + fi +} + +libatomic() { + pkgdesc="GCC Atomic library" + depends= + replaces="gcc" + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/${_target:+$CTARGET/}lib/libatomic.so.* "$subpkgdir"/usr/lib/ +} + +libcxx() { + pkgdesc="GNU C++ standard runtime library" + depends= + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/${_target:+$CTARGET/}lib/libstdc++.so.* "$subpkgdir"/usr/lib/ +} + +gpp() { + pkgdesc="GNU C++ standard library and compiler" + depends="libstdc++=$_gccrel gcc=$_gccrel libc-dev" + mkdir -p "$subpkgdir/$_gcclibexec" \ + "$subpkgdir"/usr/bin \ + "$subpkgdir"/usr/${_target:+$CTARGET/}include \ + "$subpkgdir"/usr/${_target:+$CTARGET/}lib \ + + mv "$pkgdir/$_gcclibexec/cc1plus" "$subpkgdir/$_gcclibexec/" + + mv "$pkgdir"/usr/${_target:+$CTARGET/}lib/*++* "$subpkgdir"/usr/${_target:+$CTARGET/}lib/ + mv "$pkgdir"/usr/${_target:+$CTARGET/}include/c++ "$subpkgdir"/usr/${_target:+$CTARGET/}include/ + mv "$pkgdir"/usr/bin/*++ "$subpkgdir"/usr/bin/ +} + +libobjc() { + pkgdesc="GNU Objective-C runtime" + replaces="objc" + depends= + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/${_target:+$CTARGET/}lib/libobjc.so.* "$subpkgdir"/usr/lib/ +} + +objc() { + pkgdesc="GNU Objective-C" + replaces="gcc" + depends="libc-dev gcc=$_gccrel libobjc=$_gccrel" + + mkdir -p "$subpkgdir"/$_gcclibdir/include \ + "$subpkgdir"/usr/lib + mv "$pkgdir"/$_gcclibdir/include/objc "$subpkgdir"/$_gcclibdir/include/ + mv "$pkgdir"/usr/lib/libobjc.so "$pkgdir"/usr/lib/libobjc.a \ + "$subpkgdir"/usr/lib/ +} + +libgcc() { + pkgdesc="GNU C compiler runtime libraries" + depends= + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/${_target:+$CTARGET/}lib/libgcc_s.so.* "$subpkgdir"/usr/lib/ +} + +libgomp() { + pkgdesc="GCC shared-memory parallel programming API library" + depends= + replaces="gcc" + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/${_target:+$CTARGET/}lib/libgomp.so.* "$subpkgdir"/usr/lib/ +} + +java() { + pkgdesc="Java support for GCC" + depends="zlib-dev gcc=$_gccrel libgcj=$_gccrel" + + mkdir -p "$subpkgdir"/usr/bin "$subpkgdir"/usr/lib "$subpkgdir"/$_gcclibdir/ + cd "$pkgdir"/usr/bin + mv *gcj *gcj-dbtool *gjavah *gcjh *jcf-dump "$subpkgdir"/usr/bin/ + cd "$pkgdir" + for i in $(find usr/ -name ecj1 -o -name jc1 -o -name jvgenmain); do + mkdir -p "$subpkgdir"/${i%/*} + mv "$pkgdir"/$i "$subpkgdir"/$i + done + for i in "$pkgdir"/usr/lib/libgcj*.so; do + if [ -L "$i" ]; then + mv "$i" "$subpkgdir"/usr/lib/ + fi + done + mkdir -p "$subpkgdir"/usr/share/gcc-6.4.0/python + mv "$pkgdir"/usr/share/gcc-6.4.0/python/libjava \ + "$subpkgdir"/usr/share/gcc-6.4.0/python + mv "$pkgdir"/usr/lib/libgij.so "$subpkgdir"/usr/lib/ + mv "$pkgdir"/usr/lib/libgcj.spec "$subpkgdir"/$_gcclibdir/ +} + +libgcj() { + pkgdesc="Java runtime library for gcc" + # libgcj_bc.so moved from gcc-java to libgcj + replaces="gcc-java" + depends= + + mkdir -p "$subpkgdir"/usr/bin + cd "$pkgdir"/usr/bin + mv aot-compile gappletviewer gc-analyze gij gjar gjarsigner gkeytool\ + gnative2ascii gorbd grmic grmid grmiregistry gserialver \ + gtnameserv jv-convert rebuild-gcj-db \ + "$subpkgdir"/usr/bin/ + cd "$pkgdir" + for i in $(find usr/lib -name jc1 -o -name jvgenmain); do + mkdir -p "$subpkgdir"/${i%/*} + mv "$pkgdir"/$i "$subpkgdir"/$i + done + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/lib/gcj-* \ + "$pkgdir"/usr/lib/libgcj_bc.so \ + "$pkgdir"/usr/lib/libgcj*.so.* \ + "$pkgdir"/usr/lib/libgij.so.* \ + "$pkgdir"/usr/lib/logging.properties \ + "$pkgdir"/usr/lib/security \ + "$subpkgdir"/usr/lib/ + + mkdir -p "$subpkgdir"/usr/lib/pkgconfig + mv "$pkgdir"/usr/lib/pkgconfig/libgcj* "$subpkgdir"/usr/lib/pkgconfig/ + + mkdir -p "$subpkgdir"/usr/share/ + mv "$pkgdir"/usr/share/java "$subpkgdir"/usr/share/ +} + +libgo() { + pkgdesc="Go runtime library for GCC" + depends= + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/lib/libgo.so.* "$subpkgdir"/usr/lib/ +} + +go() { + pkgdesc="Go support for GCC" + depends="gcc=$_gccrel libgo=$_gccrel" + + mkdir -p "$subpkgdir"/$_gcclibexec \ + "$subpkgdir"/usr/lib \ + "$subpkgdir"/usr/bin + mv "$pkgdir"/usr/lib/go "$subpkgdir"/usr/lib/ + mv "$pkgdir"/usr/bin/*gccgo "$subpkgdir"/usr/bin/ + mv "$pkgdir"/usr/bin/*go "$subpkgdir"/usr/bin + mv "$pkgdir"/usr/bin/*gofmt "$subpkgdir"/usr/bin + mv "$pkgdir"/$_gcclibexec/go1 "$subpkgdir"/$_gcclibexec/ + mv "$pkgdir"/$_gcclibexec/cgo "$subpkgdir"/$_gcclibexec/ + mv "$pkgdir"/usr/lib/libgo.a \ + "$pkgdir"/usr/lib/libgo.so \ + "$pkgdir"/usr/lib/libgobegin.a \ + "$pkgdir"/usr/lib/libgolibbegin.a \ + "$pkgdir"/usr/lib/libnetgo.a \ + "$subpkgdir"/usr/lib/ +} + +libgfortran() { + pkgdesc="Fortran runtime library for GCC" + depends= + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/lib/libgfortran.so.* "$subpkgdir"/usr/lib/ +} + +libquadmath() { + replaces="gcc" + pkgdesc="128-bit math library for GCC" + depends= + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/lib/libquadmath.so.* "$subpkgdir"/usr/lib/ +} + +gfortran() { + pkgdesc="GNU Fortran Compiler" + depends="gcc=$_gccrel libgfortran=$_gccrel" + $LIBQUADMATH && depends="$depends libquadmath=$_gccrel" + replaces="gcc" + + mkdir -p "$subpkgdir"/$_gcclibexec \ + "$subpkgdir"/$_gcclibdir \ + "$subpkgdir"/usr/lib \ + "$subpkgdir"/usr/bin + mv "$pkgdir"/usr/bin/*gfortran "$subpkgdir"/usr/bin/ + mv "$pkgdir"/usr/lib/libgfortran.a \ + "$pkgdir"/usr/lib/libgfortran.so \ + "$subpkgdir"/usr/lib/ + if $LIBQUADMATH; then + mv "$pkgdir"/usr/lib/libquadmath.a \ + "$pkgdir"/usr/lib/libquadmath.so \ + "$subpkgdir"/usr/lib/ + fi + mv "$pkgdir"/$_gcclibexec/f951 "$subpkgdir"/$_gcclibexec + mv "$pkgdir"/usr/lib/libgfortran.spec "$subpkgdir"/$_gcclibdir +} + +libgnat() { + pkgdesc="GNU Ada runtime shared libraries" + depends= + + mkdir -p "$subpkgdir"/usr/lib + mv "$pkgdir"/usr/lib/libgna*.so "$subpkgdir"/usr/lib/ +} + +gnat() { + pkgdesc="Ada support for GCC" + depends="gcc=$_gccrel" + [ "$CHOST" = "$CTARGET" ] && depends="$depends libgnat=$_gccrel" + + mkdir -p "$subpkgdir"/$_gcclibexec \ + "$subpkgdir"/$_gcclibdir \ + "$subpkgdir"/usr/bin + mv "$pkgdir"/$_gcclibexec/*gnat* "$subpkgdir"/$_gcclibexec/ + mv "$pkgdir"/$_gcclibdir/*ada* "$subpkgdir"/$_gcclibdir/ + mv "$pkgdir"/usr/bin/*gnat* "$subpkgdir"/usr/bin/ +} + +sha512sums="02c60e54527c7adf584798d5251f8a0b80c93d5deafce82501b2c28e6692e0bd783927bbfc4bc527a863c0cccc025150a34740a9e29badb02d4b48e56a8aba90 gcc-6.4.0.tar.xz +28f8c6fdbcb19e950b1d0bafb3bcc7a8cba87bc673aa6027cece116599cdee80f0cf5e95a1440544890239f5c754e8a93ab46d9daedd937faef445d7ea33b226 ecj-4.9.jar +a1335adc2fbee98e36c4437ff2587771b98ed4180726779020f65039498235626a411cdb0100dbd20cd19d12f0d94f9a21af179ff624676c28cead9d60598b5d 001_all_default-ssp-strong.patch +e36e95b81489163abd6fe9d58f7867bdca43e61143afacbfb17f4698c0b16ec5fd0061d8fab7b2ae615540bebd721c2e2227f80401b4e7fc253da9da62e6b513 002_all_default-relro.patch +f86466c62b8291fac46f9c250c7ad8fa5ab7b1cce2504442fd07ddc4543665b317ae28951f244e39aba29aeaf3fff252ec4f6a147aa16adb2b7aed747dd89188 003_all_default-fortify-source.patch +51282fea54c7e616367bbeb2479ba13fec6f24eb47bd04e2071907b3b36273b2ff24676f46ef8d22f241c8ab4857307861eee076eab66797c3a50a8ecaa1809a 005_all_default-as-needed.patch +3398386dd1e079d6545dd9799adc799c6b80e3984fac6899d0e1a7ee21b66d0c7e53cddf17a65d590c883db750f9f79aaedd857355a8b9f7fb9476c906237919 011_all_default-warn-format-security.patch +9adb0d2b9b67dd957df6c609b8714c7c078efb52cd88770905c37c67827be8fc83d1125037b9c29d77db21ce78756aa2bb0bacdb0b98d869ac126da76a298e21 012_all_default-warn-trampolines.patch +d35a3ac7e13a4446921a90e1ff3eec1079840c845f9d523c868e24ae21f94cf69ba041de5341ebef96432a6f57598e223381d4286e8fb8baaa25906707f29fbd 020_all_msgfmt-libstdc++-link.patch +840070a3c423e6206aaa6e63e1d9a0fcd6efd53626cd1240a193f0b60aa5d84216acc4a2a4fa8bce74549b07e6a316b01d638f20cea13dc62473491a302fb3d6 050_all_libiberty-asprintf.patch +0a0bc72b9366158f5d23fff1928e756fdd212433bac6ab1f00d632f241382820db8db5d475ddf11ea020eaf7e2e71b12fb9b1c3c870cf84adf6c2b16f15aabca 051_all_libiberty-pic.patch +e7a2eb1b1870e199d6fd753d065781575656fa12baa264f96c5d179689d88c31b8a3f92a5dae96088c05e96aa2bda138364ad7dbcc79e1819a102f192cbb7bab 053_all_libitm-no-fortify-source.patch +e87da18aa7ab92b02b06168658c63b42a6c73a08fad2a30f81ef6296100fdbe3c3a91548fd0cb24eaf591e862bb08e4b67249bc4b977b07da33523aee0c686bc 067_all_gcc-poison-system-directories.patch +4a328d1e1a56c20166307edcfa322068915784d9c08025b7f81cf69714da48fc266b6d34f77b9135c2f10da830d9df408276a1b78d1fd218637c2823506593c2 090_all_pr55930-dependency-tracking.patch +ef052d0c3c9642fcb5ed570069c5a49c8ef523c47ac8ce3f201a801766f72ae4ff7c3725a70ee66e52c0fb559621e35fe0cf5b88b901d71ceadd381f49653a08 201-cilkrts.patch +808e206f5e107084156fba333d4e091dcbd62f5d7756142bc292d4b0a52619f8c2aaca3617defc2f5b6552ba0439aebd33f4141329d88eab6ddf2dd637d92c08 203-libgcc_s.patch +fc0de05b36613b732a0222ea005c90653c6a40d6761b6894af2419272f4e74875f37e26af33a9b9940669ef89269c44c46d17ca5bcd54b5cd1176e5eaf2992c1 204-linux_libc_has_function.patch +98473bcaa77903a223ca9b0d2087c0921b287a2816d308cc32c8fe009e6cbf5dd1ae7fba27794ab8d9c09e117fe534413d91a464d1218474fc123ce0adfdc2c1 205-nopie.patch +3287d5b443bea8ec64132bcabe869c738ae98ea8f1a86df1c5d18c927f8816edbfcefeefc47792dbbb2bcacf50319af00e01b3735d34525913b64350770ad453 207-static-pie.patch +d08d7ead2de0429e5c9055d5b029ec2be9a8c821d22cecaf9b51f633652c493333f98963d9267fa2fa63850c50ae5eefd5f59e5910ec10d20044dac082182a8b libgcc-always-build-gcceh.a.patch +600fe5098dc54edaa9808fd5717af9dec058953f9ad37d49cfba1db4f7e9a7a8f02019342f75157fc575946fa693259422184de27b7ecc8386d9f3ecc0f7cc5d gcc-4.9-musl-fortify.patch +dbe0ee917fc7668571722364ab7c806731e3a31e8bfa30b4941b28b16b877d2a32b4a3897ef533399a28f82d43cac9b28e92de0493f0e779046db56584e07fa4 gcc-6.1-musl-libssp.patch +bda845a6aa1854d2c883910b115f79ccfa93dfc2b5eac69a3a236d83eb34cadc140731d616ffc24698c7abc8878dd15f231bcc5119f1860e575a120b311706c7 boehm-gc-musl.patch +fa62556719449caec6b2b434355bfbcaa5ae55ffe017b3e1f827f66a2aae21b79c571ee7a4ce723ea69169bc3a6447e73650991a200cc372adf2f102677518d7 gcc-pure64.patch +2253941f3d19b6d08801d3782f5f5ed56c3b73fbc9d3561a8f01c702963ac4fab91599c686076e7081eb6a80c37ccd33591ae978996d6eee1dc0ce0f1c50259a fix-gcj-stdgnu14-link.patch +f89ddeb21bc8f97e6a850a6b70b4501a8f3e49a4bc8cc82897488decda5d98ad01cb7f6c8b392d452e9579924a523bc75da6e0648c1c976d42e40af48b10343b fix-gcj-musl.patch +54d67cc008b735e47771314171930c5d8b8f5f5dc97fcf4214824c105c808f3e75d22d5a4fdf5068ed0457fa0d46c60cfb442e276259a4a5e9b8722a027d18e6 fix-gcj-iconv-musl.patch +abe9aaf9aa956058d0386a4396a511d176a46bb3906b90e952383646cdc158cbeb0a5dc616a1ccb1ca7d49fd0b5e351532aa15a3b13362abbf1ca4266f54a687 gcc-4.8-build-args.patch +35d6d59f0b7b968f282f56767c9e0823a7bdc5aa0d450aca50fbd802649a7ca608b47671244a3faa208a9b0d6832cabb5a22724157dc817b2c0ad63d09f93282 fix-cxxflags-passing.patch +9016b257abd8fa981de44a49512e35db814d1cbb47c1a87cd31c12d4ae20b13e9e149fe41691a7ec3c95bbcfde8a79194a8d2eaf547ceade3a246fad67c47dd8 ada-fixes.patch +3f5bc334d9f73d06f5f7c876738d02356acdd08958bea0e4d2095ebf15c2c2ec4e411abdae0297505ae9a1699ca01b17338e853184e84663203b192b0d35fc19 ada-shared.patch +631d4bdef6d8bde34df7978bb53ec28c3c909cf1f87139e5f148138d0f09adc58b41ecf0148bbf50fb4bc916c411e9bf8a2b6c046c75c0e77d754d8c35bcd4d7 ada-musl.patch +fa44c8158111627aa0e91c43e7cc3aa38642c2041c96532dd4f0932dae4d6f92ea2850b683abcf10e7e120299d42ea6b69adc00002a514c76be8e39e99fa052b ada-aarch64-multiarch.patch +4b4a0ff306a8ef34ff6e3284fbfca869012164a47ba7cb099085c1dd03e6ca0cdd462f82710e08c9a02895adc7484e4c5eef17b5aa264cf5d978fe8ad78eea93 300-main-gcc-add-musl-s390x-dynamic-linker.patch +385bc2fa50204f678964e5148c6170f572701dab920fbec8301f505bda34d182cde0adb7da042fee71719e12fb59f59181897f9b1bb4f4716ff59aad46ca1998 310-build-gcj-s390x.patch +f4ef08454e28c8732db69115e4998ec153399e8d229dd27f923dbdcf57b68128a65640d026cc7f45b58ba8764ab1eb575d4eb6d6dfc550a87a183f8b94e76181 320-libffi-gnulinux.patch +8efd028febb962ae100be32f72f7450c4f77d67ad96a5f47072136cdf47043f9d54835a87c7ab5aaa0fa0108c4c7a97ba2d7732d5aaf2efce70fe1f7e1c39d6e 330-gccgo-link-to-ucontext.patch +24c8708f64b9b7945b3f07e9bbecf17ab8bcde2524f49cbd694ca2f6146ccc3f13bb027db282f326525ea79d50a2868fa3fa2b0d688a914b5ea77bbfd7e5cbe4 331-gccgo-use-real-off_t-type.patch +cf19fcc6abee70210a9061e5385fe361a5eb59a74f7d34297420a53e351400da23a060164bef5b322daba4be90019481731acf93c45fb5a93430018f1aa7ce35 332-gccgo-remove-ustat.patch +d5eb8d289a1de1f9d85d5451a81265a1aac3eea79a555cc4bfaa60cb7c3f80c00ee1ea3791a8069bc22783f3534d6ad20bfaa4e11252f49f9ffa27843315c0ee libgo-musl-1.2.3.patch +01c71cd5881fc07ea3b9b980697e89b3ca0fe98502958ceafc3fca18b2604c844e2f457feab711baf8e03f00a5383b0e38aac7eb954034e306f43d4a37f165ed fix-rs6000-pie.patch +1860593584f629d24d5b6db14b0a3412e9f93449b663aaa4981301a0923db0159314905e694f27366fbfef72dce06636ab6df86862b7e9e9564847e03bee82c1 add-classic_table-support.patch +4e1b421ed72668b66ecbcb0a34afa99d2a34cb2ea9ee51c4aad605fc8a0e94e3bfbabae4ebe236efc5ec86fc01a472cbe93f36fe25cf579714939d8102a9b84a lra-pentium.patch +67a75a94fdba69de96b98dbc2978a50cb197857c464b81f7c956176da7066b3be937e40cb15e0870fc1e7382d662c5101bcd18cf457fc4112de41802042b51c4 gcc-5.4.0-locale.patch +ca9e2747fc0ed5b5c35a7df6ae48482855c2663882b5e7a86e65efa5910b3be77380361fe21668718a3e68f6362306a440fa86bff6c50b4d92d6c75ce65a47e8 isl-fix.patch" diff --git a/legacy/gcc6/ada-aarch64-multiarch.patch b/legacy/gcc6/ada-aarch64-multiarch.patch new file mode 100644 index 000000000..ac60b6f6a --- /dev/null +++ b/legacy/gcc6/ada-aarch64-multiarch.patch @@ -0,0 +1,16 @@ +--- gcc-6.4.0/gcc/ada/gcc-interface/Makefile.in.orig ++++ gcc-6.4.0/gcc/ada/gcc-interface/Makefile.in +@@ -2042,13 +2042,8 @@ + system.ads<system-linux-x86_64.ads + ## ^^ Note the above is a pretty-close placeholder. + +- ifneq (,$(or $(filter aarch64-linux-gnu, $(shell $(GCC_FOR_TARGET) $(GNATLIBCFLAGS) -print-multiarch)), $(filter ../lib64, $(shell $(GCC_FOR_TARGET) $(GNATLIBCFLAGS) -print-multi-os-directory)))) + LIBGNAT_TARGET_PAIRS = \ + $(LIBGNAT_TARGET_PAIRS_COMMON) $(LIBGNAT_TARGET_PAIRS_64) +- else +- LIBGNAT_TARGET_PAIRS = \ +- $(LIBGNAT_TARGET_PAIRS_COMMON) $(LIBGNAT_TARGET_PAIRS_32) +- endif + + TOOLS_TARGET_PAIRS = \ + mlib-tgt-specific.adb<mlib-tgt-specific-linux.adb \ diff --git a/legacy/gcc6/ada-fixes.patch b/legacy/gcc6/ada-fixes.patch new file mode 100644 index 000000000..ba4ea42b4 --- /dev/null +++ b/legacy/gcc6/ada-fixes.patch @@ -0,0 +1,35 @@ +--- gcc-6.1.0.orig/gcc/ada/cal.c ++++ gcc-6.1.0/gcc/ada/cal.c +@@ -49,6 +49,7 @@ + #include <time.h> + #else + #include <sys/time.h> ++#include <time.h> + #endif + + #ifdef __MINGW32__ +--- gcc-6.1.0.orig/gcc/ada/terminals.c ++++ gcc-6.1.0/gcc/ada/terminals.c +@@ -1068,13 +1068,6 @@ + #include <stdio.h> + #include <stdlib.h> + +-/* On some system termio is either absent or including it will disable termios +- (HP-UX) */ +-#if !defined (__hpux__) && !defined (BSD) && !defined (__APPLE__) \ +- && !defined (__rtems__) +-# include <termio.h> +-#endif +- + #include <sys/ioctl.h> + #include <termios.h> + #include <fcntl.h> +@@ -1169,7 +1162,7 @@ + char *slave_name = NULL; + + #ifdef USE_GETPT +- master_fd = getpt (); ++ master_fd = posix_openpt (O_RDWR); + #elif defined (USE_OPENPTY) + status = openpty (&master_fd, &slave_fd, NULL, NULL, NULL); + #elif defined (USE_CLONE_DEVICE) diff --git a/legacy/gcc6/ada-musl.patch b/legacy/gcc6/ada-musl.patch new file mode 100644 index 000000000..464c3d57d --- /dev/null +++ b/legacy/gcc6/ada-musl.patch @@ -0,0 +1,137 @@ +diff -rup gcc-5.1.0/gcc.orig/ada/adaint.c gcc-5.1.0/gcc/ada/adaint.c +--- gcc-5.1.0/gcc.orig/ada/adaint.c 2015-02-20 11:48:57.000000000 +0000 ++++ gcc-5.1.0/gcc/ada/adaint.c 2015-06-02 10:47:51.672767476 +0000 +@@ -70,6 +70,11 @@ + #include <sys/param.h> + #include <sys/pstat.h> + #endif ++ ++#if defined (linux) ++#define _GNU_SOURCE 1 ++#include <sched.h> ++#endif + + #ifdef __PikeOS__ + #define __BSD_VISIBLE 1 +@@ -3057,8 +3062,6 @@ __gnat_lwp_self (void) + return (void *) syscall (__NR_gettid); + } + +-#include <sched.h> +- + /* glibc versions earlier than 2.7 do not define the routines to handle + dynamically allocated CPU sets. For these targets, we use the static + versions. */ +@@ -3067,7 +3070,7 @@ __gnat_lwp_self (void) + + /* Dynamic cpu sets */ + +-cpu_set_t * ++void * + __gnat_cpu_alloc (size_t count) + { + return CPU_ALLOC (count); +@@ -3080,33 +3083,33 @@ __gnat_cpu_alloc_size (size_t count) + } + + void +-__gnat_cpu_free (cpu_set_t *set) ++__gnat_cpu_free (void *set) + { +- CPU_FREE (set); ++ CPU_FREE ((cpu_set_t *) set); + } + + void +-__gnat_cpu_zero (size_t count, cpu_set_t *set) ++__gnat_cpu_zero (size_t count, void *set) + { +- CPU_ZERO_S (count, set); ++ CPU_ZERO_S (count, (cpu_set_t *) set); + } + + void +-__gnat_cpu_set (int cpu, size_t count, cpu_set_t *set) ++__gnat_cpu_set (int cpu, size_t count, void *set) + { + /* Ada handles CPU numbers starting from 1, while C identifies the first + CPU by a 0, so we need to adjust. */ +- CPU_SET_S (cpu - 1, count, set); ++ CPU_SET_S (cpu - 1, count, (cpu_set_t *) set); + } + + #else /* !CPU_ALLOC */ + + /* Static cpu sets */ + +-cpu_set_t * ++void * + __gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED) + { +- return (cpu_set_t *) xmalloc (sizeof (cpu_set_t)); ++ return xmalloc (sizeof (cpu_set_t)); + } + + size_t +@@ -3116,23 +3119,23 @@ __gnat_cpu_alloc_size (size_t count ATTR + } + + void +-__gnat_cpu_free (cpu_set_t *set) ++__gnat_cpu_free (void *set) + { + free (set); + } + + void +-__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, cpu_set_t *set) ++__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, void *set) + { +- CPU_ZERO (set); ++ CPU_ZERO ((cpu_set_t *) set); + } + + void +-__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, cpu_set_t *set) ++__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, void *set) + { + /* Ada handles CPU numbers starting from 1, while C identifies the first + CPU by a 0, so we need to adjust. */ +- CPU_SET (cpu - 1, set); ++ CPU_SET (cpu - 1, (cpu_set_t *) set); + } + #endif /* !CPU_ALLOC */ + #endif /* linux */ +diff -rup gcc-5.1.0/gcc.orig/ada/adaint.h gcc-5.1.0/gcc/ada/adaint.h +--- gcc-5.1.0/gcc.orig/ada/adaint.h 2015-01-27 17:20:27.000000000 +0000 ++++ gcc-5.1.0/gcc/ada/adaint.h 2015-06-02 10:47:23.188910894 +0000 +@@ -287,13 +287,11 @@ extern void *__gnat_lwp_self (voi + + /* Routines for interface to required CPU set primitives */ + +-#include <sched.h> +- +-extern cpu_set_t *__gnat_cpu_alloc (size_t); ++extern void * __gnat_cpu_alloc (size_t); + extern size_t __gnat_cpu_alloc_size (size_t); +-extern void __gnat_cpu_free (cpu_set_t *); +-extern void __gnat_cpu_zero (size_t, cpu_set_t *); +-extern void __gnat_cpu_set (int, size_t, cpu_set_t *); ++extern void __gnat_cpu_free (void *); ++extern void __gnat_cpu_zero (size_t, void *); ++extern void __gnat_cpu_set (int, size_t, void *); + #endif + + #if defined (_WIN32) +diff -rup gcc-5.1.0/gcc.orig/ada/gcc-interface/Makefile.in gcc-5.1.0/gcc/ada/gcc-interface/Makefile.in +--- gcc-5.1.0/gcc.orig/ada/gcc-interface/Makefile.in 2015-04-09 20:29:28.000000000 +0000 ++++ gcc-5.1.0/gcc/ada/gcc-interface/Makefile.in 2015-06-02 10:47:23.188910894 +0000 +@@ -1910,7 +1910,7 @@ ifeq ($(strip $(filter-out powerpc% linu + endif + + # ARM linux, GNU eabi +-ifeq ($(strip $(filter-out arm% linux-gnueabi%,$(target_cpu) $(target_os))),) ++ifeq ($(strip $(filter-out arm% linux-gnueabi% linux-musleabi% linux-muslgnueabi%,$(target_cpu) $(target_os))),) + LIBGNAT_TARGET_PAIRS = \ + a-intnam.ads<a-intnam-linux.ads \ + s-inmaop.adb<s-inmaop-posix.adb \ diff --git a/legacy/gcc6/ada-shared.patch b/legacy/gcc6/ada-shared.patch new file mode 100644 index 000000000..6f1c16aff --- /dev/null +++ b/legacy/gcc6/ada-shared.patch @@ -0,0 +1,30 @@ +Index: b/gcc/ada/link.c +=================================================================== +--- a/gcc/ada/link.c ++++ b/gcc/ada/link.c +@@ -105,9 +105,9 @@ + + #elif defined (__FreeBSD__) + const char *__gnat_object_file_option = "-Wl,@"; +-const char *__gnat_run_path_option = "-Wl,-rpath,"; +-char __gnat_shared_libgnat_default = STATIC; +-char __gnat_shared_libgcc_default = STATIC; ++const char *__gnat_run_path_option = ""; ++char __gnat_shared_libgnat_default = SHARED; ++char __gnat_shared_libgcc_default = SHARED; + int __gnat_link_max = 8192; + unsigned char __gnat_objlist_file_supported = 1; + const char *__gnat_object_library_extension = ".a"; +@@ -127,9 +127,9 @@ + + #elif defined (linux) || defined(__GLIBC__) + const char *__gnat_object_file_option = "-Wl,@"; +-const char *__gnat_run_path_option = "-Wl,-rpath,"; +-char __gnat_shared_libgnat_default = STATIC; +-char __gnat_shared_libgcc_default = STATIC; ++const char *__gnat_run_path_option = ""; ++char __gnat_shared_libgnat_default = SHARED; ++char __gnat_shared_libgcc_default = SHARED; + int __gnat_link_max = 8192; + unsigned char __gnat_objlist_file_supported = 1; + const char *__gnat_object_library_extension = ".a"; diff --git a/legacy/gcc6/add-classic_table-support.patch b/legacy/gcc6/add-classic_table-support.patch new file mode 100644 index 000000000..e74929302 --- /dev/null +++ b/legacy/gcc6/add-classic_table-support.patch @@ -0,0 +1,152 @@ +--- gcc-6.4.0/libstdc++-v3/config/os/generic/ctype_base.h.old 2016-01-04 08:30:50.652828000 -0600 ++++ gcc-6.4.0/libstdc++-v3/config/os/generic/ctype_base.h 2017-10-16 07:51:26.226276759 -0500 +@@ -40,19 +40,27 @@ + + // NB: Offsets into ctype<char>::_M_table force a particular size + // on the mask type. Because of this, we don't use an enum. +- typedef unsigned int mask; +- static const mask upper = 1 << 0; +- static const mask lower = 1 << 1; +- static const mask alpha = 1 << 2; +- static const mask digit = 1 << 3; +- static const mask xdigit = 1 << 4; +- static const mask space = 1 << 5; +- static const mask print = 1 << 6; +- static const mask graph = (1 << 2) | (1 << 3) | (1 << 9); // alnum|punct +- static const mask cntrl = 1 << 8; +- static const mask punct = 1 << 9; +- static const mask alnum = (1 << 2) | (1 << 3); // alpha|digit +- static const mask blank = 1 << 10; ++ typedef unsigned short int mask; ++/* horrible ugly code from glibc */ ++#ifndef _ISbit ++# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++# define _ISbit(i) (1 << (i)) ++# else ++# define _ISbit(i) (i < 8 ? (1 << i << 8) : (1 << i >> 8)) ++# endif ++#endif ++ static const mask upper = _ISbit(0); ++ static const mask lower = _ISbit(1); ++ static const mask alpha = _ISbit(2); ++ static const mask digit = _ISbit(3); ++ static const mask xdigit = _ISbit(4); ++ static const mask space = _ISbit(5); ++ static const mask print = _ISbit(6); ++ static const mask graph = _ISbit(7); ++ static const mask cntrl = _ISbit(9); ++ static const mask punct = _ISbit(10); ++ static const mask alnum = _ISbit(11); ++ static const mask blank = _ISbit(8); + }; + + _GLIBCXX_END_NAMESPACE_VERSION +--- gcc-6.4.0/libstdc++-v3/config/os/generic/ctype_configure_char.cc.old 2016-01-04 08:30:50.652828000 -0600 ++++ gcc-6.4.0/libstdc++-v3/config/os/generic/ctype_configure_char.cc 2017-10-16 08:37:57.986260218 -0500 +@@ -40,7 +40,105 @@ + + const ctype_base::mask* + ctype<char>::classic_table() throw() +- { return 0; } ++ { ++ static ctype_base::mask mask[256] = { ++ cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, ++ cntrl, cntrl | blank | space, cntrl | space, cntrl | space, ++ cntrl | space, cntrl | space, cntrl, cntrl, ++ cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, ++ cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, cntrl, ++ print | space | blank, ++ print | punct, print | punct, ++ print | punct, print | punct, ++ print | punct, print | punct, ++ print | punct, print | punct, ++ print | punct, print | punct, ++ print | punct, print | punct, ++ print | punct, print | punct, ++ print | punct, ++ print | alnum | digit | xdigit, print | alnum | digit | xdigit, ++ print | alnum | digit | xdigit, print | alnum | digit | xdigit, ++ print | alnum | digit | xdigit, print | alnum | digit | xdigit, ++ print | alnum | digit | xdigit, print | alnum | digit | xdigit, ++ print | alnum | digit | xdigit, print | alnum | digit | xdigit, ++ print | punct, print | punct, ++ print, print, print, ++ print | punct, print, ++ print | alnum | xdigit | alpha | upper, ++ print | alnum | xdigit | alpha | upper, ++ print | alnum | xdigit | alpha | upper, ++ print | alnum | xdigit | alpha | upper, ++ print | alnum | xdigit | alpha | upper, ++ print | alnum | xdigit | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | alnum | alpha | upper, ++ print | punct, print | punct, print | punct, ++ print | punct, print | punct, print | punct, ++ print | alnum | xdigit | alpha | lower, ++ print | alnum | xdigit | alpha | lower, ++ print | alnum | xdigit | alpha | lower, ++ print | alnum | xdigit | alpha | lower, ++ print | alnum | xdigit | alpha | lower, ++ print | alnum | xdigit | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | alnum | alpha | lower, ++ print | punct, print | punct, print | punct, print | punct, ++ cntrl, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0 ++ }; ++ return mask; ++ } + + ctype<char>::ctype(__c_locale, const mask* __table, bool __del, + size_t __refs) diff --git a/legacy/gcc6/boehm-gc-musl.patch b/legacy/gcc6/boehm-gc-musl.patch new file mode 100644 index 000000000..2f106cba1 --- /dev/null +++ b/legacy/gcc6/boehm-gc-musl.patch @@ -0,0 +1,62 @@ +--- gcc-4.8.1/boehm-gc/os_dep.c.orig 2013-09-17 07:46:00.969884340 +0000 ++++ gcc-4.8.1/boehm-gc/os_dep.c 2013-09-17 06:53:53.629884946 +0000 +@@ -26,7 +26,7 @@ + # define __KERNEL__ + # include <asm/signal.h> + # undef __KERNEL__ +-# else ++# elif defined(__GLIBC__) + /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */ + /* struct sigcontext. libc6 (glibc2) uses "struct sigcontext" in */ + /* prototypes, so we have to include the top-level sigcontext.h to */ +--- gcc-4.8.2/boehm-gc/dyn_load.c.orig 2014-02-17 14:13:09.519850231 +0200 ++++ gcc-4.8.2/boehm-gc/dyn_load.c 2014-02-17 14:14:27.906093514 +0200 +@@ -459,9 +459,7 @@ + /* For glibc 2.2.4+. Unfortunately, it doesn't work for older */ + /* versions. Thanks to Jakub Jelinek for most of the code. */ + +-# if (defined(LINUX) || defined (__GLIBC__)) /* Are others OK here, too? */ \ +- && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ +- || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) ++# if (defined(LINUX) || defined (__GLIBC__)) + + /* We have the header files for a glibc that includes dl_iterate_phdr. */ + /* It may still not be available in the library on the target system. */ +--- gcc-4.8.2/boehm-gc/include/private/gcconfig.h.orig 2014-02-17 14:14:36.026049422 +0200 ++++ gcc-4.8.2/boehm-gc/include/private/gcconfig.h 2014-02-17 14:17:11.345207887 +0200 +@@ -684,7 +684,7 @@ + # ifdef __ELF__ + # define DYNAMIC_LOADING + # include <features.h> +-# if defined(__GLIBC__)&& __GLIBC__>=2 ++# if 1 + # define SEARCH_FOR_DATA_START + # else /* !GLIBC2 */ + extern char **__environ; +@@ -1147,7 +1147,7 @@ + # define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff)) + # endif + # include <features.h> +-# if defined(__GLIBC__) && __GLIBC__ >= 2 ++# if 1 + # define SEARCH_FOR_DATA_START + # else + extern char **__environ; +@@ -1367,7 +1367,7 @@ + # define HBLKSIZE 4096 + # endif + # define USE_GENERIC_PUSH_REGS +-# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2 ++# if 1 + # define LINUX_STACKBOTTOM + # else + # define STACKBOTTOM 0x80000000 +@@ -1858,7 +1858,7 @@ + # ifdef __ELF__ + # define DYNAMIC_LOADING + # include <features.h> +-# if defined(__GLIBC__) && __GLIBC__ >= 2 ++# if 1 + # define SEARCH_FOR_DATA_START + # else + extern char **__environ; diff --git a/legacy/gcc6/fix-cxxflags-passing.patch b/legacy/gcc6/fix-cxxflags-passing.patch new file mode 100644 index 000000000..8eb1de77d --- /dev/null +++ b/legacy/gcc6/fix-cxxflags-passing.patch @@ -0,0 +1,10 @@ +--- gcc-4.8.1/Makefile.in.orig ++++ gcc-4.8.1/Makefile.in +@@ -169,6 +169,7 @@ + # built for the build system to override those in BASE_FLAGS_TO_PASSS. + EXTRA_BUILD_FLAGS = \ + CFLAGS="$(CFLAGS_FOR_BUILD)" \ ++ CXXFLAGS="$(CXXFLAGS_FOR_BUILD)" \ + LDFLAGS="$(LDFLAGS_FOR_BUILD)" + + # This is the list of directories to built for the host system. diff --git a/legacy/gcc6/fix-gcj-iconv-musl.patch b/legacy/gcc6/fix-gcj-iconv-musl.patch new file mode 100644 index 000000000..b0015751e --- /dev/null +++ b/legacy/gcc6/fix-gcj-iconv-musl.patch @@ -0,0 +1,120 @@ +--- gcc-4.8.2/libjava/gnu/gcj/convert/natIconv.cc.orig 2014-02-18 18:46:14.897880526 +0200 ++++ gcc-4.8.2/libjava/gnu/gcj/convert/natIconv.cc 2014-02-18 18:50:08.766613550 +0200 +@@ -24,6 +24,13 @@ + + #ifdef HAVE_ICONV + #include <iconv.h> ++#include <endian.h> ++ ++#if __BYTE_ORDER == __BIG_ENDIAN ++#define UCS2_CHARSET "UCS-2BE" ++#else ++#define UCS2_CHARSET "UCS-2LE" ++#endif + + template<typename T> + static inline size_t +@@ -45,7 +52,7 @@ + _Jv_GetStringUTFRegion (encoding, 0, encoding->length(), buffer); + buffer[len] = '\0'; + +- iconv_t h = iconv_open ("UCS-2", buffer); ++ iconv_t h = iconv_open (UCS2_CHARSET, buffer); + if (h == (iconv_t) -1) + throw new ::java::io::UnsupportedEncodingException (encoding); + +@@ -99,18 +106,6 @@ + throw new ::java::io::CharConversionException (); + } + +- if (iconv_byte_swap) +- { +- size_t max = (old_out - outavail) / sizeof (jchar); +- for (size_t i = 0; i < max; ++i) +- { +- // Byte swap. +- jchar c = (((out[outpos + i] & 0xff) << 8) +- | ((out[outpos + i] >> 8) & 0xff)); +- outbuf[i] = c; +- } +- } +- + inpos += old_in - inavail; + return (old_out - outavail) / sizeof (jchar); + #else /* HAVE_ICONV */ +@@ -145,7 +140,7 @@ + _Jv_GetStringUTFRegion (encoding, 0, encoding->length(), buffer); + buffer[len] = '\0'; + +- iconv_t h = iconv_open (buffer, "UCS-2"); ++ iconv_t h = iconv_open (buffer, UCS2_CHARSET); + if (h == (iconv_t) -1) + throw new ::java::io::UnsupportedEncodingException (encoding); + +@@ -187,20 +182,6 @@ + char *inbuf = (char *) &chars[inpos]; + char *outbuf = (char *) &out[count]; + +- if (iconv_byte_swap) +- { +- // Ugly performance penalty -- don't use losing systems! +- temp_buffer = (jchar *) _Jv_Malloc (inlength * sizeof (jchar)); +- for (int i = 0; i < inlength; ++i) +- { +- // Byte swap. +- jchar c = (((chars[inpos + i] & 0xff) << 8) +- | ((chars[inpos + i] >> 8) & 0xff)); +- temp_buffer[i] = c; +- } +- inbuf = (char *) temp_buffer; +- } +- + size_t loop_old_in = old_in; + while (1) + { +@@ -252,44 +233,7 @@ + jboolean + gnu::gcj::convert::IOConverter::iconv_init (void) + { +- // Some versions of iconv() always return their UCS-2 results in +- // big-endian order, and they also require UCS-2 inputs to be in +- // big-endian order. For instance, glibc 2.1.3 does this. If the +- // UTF-8=>UCS-2 iconv converter has this feature, then we assume +- // that all UCS-2 converters do. (This might not be the best +- // heuristic, but is is all we've got.) +- jboolean result = false; +-#ifdef HAVE_ICONV +- iconv_t handle = iconv_open ("UCS-2", "UTF-8"); +- if (handle != (iconv_t) -1) +- { +- jchar c; +- unsigned char in[4]; +- char *inp, *outp; +- size_t inc, outc, r; +- +- // This is the UTF-8 encoding of \ufeff. At least Tru64 UNIX libiconv +- // needs the trailing NUL byte, otherwise iconv fails with EINVAL. +- in[0] = 0xef; +- in[1] = 0xbb; +- in[2] = 0xbf; +- in[3] = 0x00; +- +- inp = (char *) in; +- inc = 4; +- outp = (char *) &c; +- outc = 2; +- +- r = iconv_adapter (iconv, handle, &inp, &inc, &outp, &outc); +- // Conversion must be complete for us to use the result. +- if (r != (size_t) -1 && inc == 0 && outc == 0) +- result = (c != 0xfeff); +- +- // Release iconv handle. +- iconv_close (handle); +- } +-#endif /* HAVE_ICONV */ +- return result; ++ return false; + } + + void diff --git a/legacy/gcc6/fix-gcj-musl.patch b/legacy/gcc6/fix-gcj-musl.patch new file mode 100644 index 000000000..d26f510c0 --- /dev/null +++ b/legacy/gcc6/fix-gcj-musl.patch @@ -0,0 +1,49 @@ +--- gcc-4.8.2/libjava/gnu/classpath/natSystemProperties.cc.orig 2014-02-18 10:55:08.617678779 +0200 ++++ gcc-4.8.2/libjava/gnu/classpath/natSystemProperties.cc 2014-02-18 10:56:31.927227453 +0200 +@@ -289,7 +289,7 @@ + // just default to `en_US'. + setlocale (LC_ALL, ""); + char *locale = setlocale (LC_MESSAGES, ""); +- if (locale && strlen (locale) >= 2) ++ if (locale && strlen (locale) >= 2 && (locale[2] == '\0' || locale[2] == '_')) + { + char buf[3]; + buf[2] = '\0'; +--- gcc-4.8.2/libjava/posix-threads.cc.orig 2014-02-18 13:22:01.789933726 +0200 ++++ gcc-4.8.2/libjava/posix-threads.cc 2014-02-18 13:29:50.924058875 +0200 +@@ -657,6 +657,7 @@ + struct sched_param param; + pthread_attr_t attr; + struct starter *info; ++ size_t ss; + + if (data->flags & FLAG_START) + return; +@@ -675,8 +676,25 @@ + // Set stack size if -Xss option was given. + if (gcj::stack_size > 0) + { +- int e = pthread_attr_setstacksize (&attr, gcj::stack_size); ++ ss = gcj::stack_size; ++ } ++ else ++ { ++ int e = pthread_attr_getstacksize (&attr, &ss); ++ if (e != 0) ++ JvFail (strerror (e)); ++ ++ // Request at least 1meg of stack ++ if (ss >= 1024 * 1024) ++ ss = 0; ++ else ++ ss = 1024 * 1024; ++ } ++ ++ if (ss) ++ { ++ int e = pthread_attr_setstacksize (&attr, ss); + if (e != 0) + JvFail (strerror (e)); + } + + info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter)); diff --git a/legacy/gcc6/fix-gcj-stdgnu14-link.patch b/legacy/gcc6/fix-gcj-stdgnu14-link.patch new file mode 100644 index 000000000..2b2ce0fa5 --- /dev/null +++ b/legacy/gcc6/fix-gcj-stdgnu14-link.patch @@ -0,0 +1,35 @@ +--- gcc-6.1.0/libjava/Makefile.am ++++ gcc-6.1.0/libjava/Makefile.am +@@ -488,10 +488,14 @@ + nat_files = $(nat_source_files:.cc=.lo) + xlib_nat_files = $(xlib_nat_source_files:.cc=.lo) + ++libgcj_la_CPPFLAGS = \ ++ $(AM_CPPFLAGS) \ ++ $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ++ + # Include THREADLIBS here to ensure that the correct version of + # certain linuxthread functions get linked: + ## The mysterious backslash in the grep pattern is consumed by make. +-libgcj_la_LDFLAGS = -rpath $(toolexeclibdir) $(THREADLDFLAGS) $(extra_ldflags) $(THREADLIBS) \ ++libgcj_la_LDFLAGS = $(LIBSTDCXX_RAW_CXX_LDFLAGS) -rpath $(toolexeclibdir) $(THREADLDFLAGS) $(extra_ldflags) $(THREADLIBS) \ + $(LIBLTDL) $(SYS_ZLIBS) $(LIBJAVA_LDFLAGS_NOUNDEF) \ + -version-info `grep -v '^\#' $(srcdir)/libtool-version` \ + $(LIBGCJ_LD_SYMBOLIC_FUNCTIONS) $(LIBGCJ_LD_EXPORT_ALL) +--- gcc-6.1.0/libjava/Makefile.in ++++ gcc-6.1.0/libjava/Makefile.in +@@ -1103,9 +1103,13 @@ + nat_files = $(nat_source_files:.cc=.lo) + xlib_nat_files = $(xlib_nat_source_files:.cc=.lo) + ++libgcj_la_CPPFLAGS = \ ++ $(AM_CPPFLAGS) \ ++ $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ++ + # Include THREADLIBS here to ensure that the correct version of + # certain linuxthread functions get linked: +-libgcj_la_LDFLAGS = -rpath $(toolexeclibdir) $(THREADLDFLAGS) $(extra_ldflags) $(THREADLIBS) \ ++libgcj_la_LDFLAGS = $(LIBSTDCXX_RAW_CXX_LDFLAGS) -rpath $(toolexeclibdir) $(THREADLDFLAGS) $(extra_ldflags) $(THREADLIBS) \ + $(LIBLTDL) $(SYS_ZLIBS) $(LIBJAVA_LDFLAGS_NOUNDEF) \ + -version-info `grep -v '^\#' $(srcdir)/libtool-version` \ + $(LIBGCJ_LD_SYMBOLIC_FUNCTIONS) $(LIBGCJ_LD_EXPORT_ALL) diff --git a/legacy/gcc6/fix-rs6000-pie.patch b/legacy/gcc6/fix-rs6000-pie.patch new file mode 100644 index 000000000..1fbc31a56 --- /dev/null +++ b/legacy/gcc6/fix-rs6000-pie.patch @@ -0,0 +1,59 @@ +--- gcc-6.3.0.orig/gcc/config/rs6000/sysv4.h ++++ gcc-6.3.0/gcc/config/rs6000/sysv4.h +@@ -753,23 +753,42 @@ + #endif + + #ifdef HAVE_LD_PIE +-#define STARTFILE_LINUX_SPEC "\ +-%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \ +-%{mnewlib:ecrti.o%s;:crti.o%s} \ +-%{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ +-" CRTOFFLOADBEGIN ++#define STARTFILE_LINUX_SPEC \ ++ "%{!shared: %{pg|p|profile:gcrt1.o%s;: \ ++ %{" PIE_SPEC ":%{static:rcrt1.o%s;:Scrt1.o%s}} %{" NO_PIE_SPEC ":crt1.o%s}}} \ ++ crti.o%s %{shared:crtbeginS.o%s;: \ ++ %{" PIE_SPEC ":crtbeginS.o%s} \ ++ %{" NO_PIE_SPEC ":%{static:crtbeginT.o%s;:crtbegin.o%s}}} \ ++ %{fvtable-verify=none:%s; \ ++ fvtable-verify=preinit:vtv_start_preinit.o%s; \ ++ fvtable-verify=std:vtv_start.o%s} \ ++ " CRTOFFLOADBEGIN + #else +-#define STARTFILE_LINUX_SPEC "\ +-%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ +-%{mnewlib:ecrti.o%s;:crti.o%s} \ +-%{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ +-" CRTOFFLOADBEGIN ++#define STARTFILE_LINUX_SPEC \ ++ "%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ ++ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ ++ %{fvtable-verify=none:%s; \ ++ fvtable-verify=preinit:vtv_start_preinit.o%s; \ ++ fvtable-verify=std:vtv_start.o%s} \ ++ " CRTOFFLOADBEGIN + #endif + +-#define ENDFILE_LINUX_SPEC "\ +-%{shared|pie:crtendS.o%s;:crtend.o%s} \ +-%{mnewlib:ecrtn.o%s;:crtn.o%s} \ +-" CRTOFFLOADEND ++#ifdef HAVE_LD_PIE ++#define ENDFILE_LINUX_SPEC \ ++ "%{fvtable-verify=none:%s; \ ++ fvtable-verify=preinit:vtv_end_preinit.o%s; \ ++ fvtable-verify=std:vtv_end.o%s} \ ++ %{shared:crtendS.o%s;: %{" PIE_SPEC ":crtendS.o%s} \ ++ %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s \ ++ " CRTOFFLOADEND ++#else ++#define ENDFILE_LINUX_SPEC \ ++ "%{fvtable-verify=none:%s; \ ++ fvtable-verify=preinit:vtv_end_preinit.o%s; \ ++ fvtable-verify=std:vtv_end.o%s} \ ++ %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s \ ++ " CRTOFFLOADEND ++#endif + + #define LINK_START_LINUX_SPEC "" + diff --git a/legacy/gcc6/gcc-4.8-build-args.patch b/legacy/gcc6/gcc-4.8-build-args.patch new file mode 100644 index 000000000..c27e00961 --- /dev/null +++ b/legacy/gcc6/gcc-4.8-build-args.patch @@ -0,0 +1,41 @@ +When cross compiling a target gcc, target flags may be used on the host + +Configure identifies a number of warning flags (WARN_CFLAGS and +WARN_CXXFLAGS) from the $CC value. The cross compiler may be different +from the host compiler and may not support the same set of flags. This +leads to problems such as: + +cc1plus: error: unrecognized command line option "-Wno-narrowing" +cc1plus: error: unrecognized command line option "-Wno-overlength-strings" + +Work around this problem by removing the warning flags from the +BUILD_CXXFLAGS value, in a way similar to the BUILD_CFLAGS. + +Upstream-Status: Pending + +Signed-off-by: Mark Hatle <mark.hatle@windriver.com> + +Index: gcc-4.8.0/gcc/configure +=================================================================== +--- gcc-4.8.0.orig/gcc/configure ++++ gcc-4.8.0/gcc/configure +@@ -11720,6 +10581,7 @@ STMP_FIXINC=stmp-fixinc + if test x$build != x$host || test "x$coverage_flags" != x + then + BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' ++ BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' + BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' + fi + +Index: gcc-4.8.0/gcc/configure.ac +=================================================================== +--- gcc-4.8.0.orig/gcc/configure.ac ++++ gcc-4.8.0/gcc/configure.ac +@@ -1901,6 +1901,7 @@ STMP_FIXINC=stmp-fixinc AC_SUBST(STMP_F + if test x$build != x$host || test "x$coverage_flags" != x + then + BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' ++ BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)' + BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' + fi + diff --git a/legacy/gcc6/gcc-4.9-musl-fortify.patch b/legacy/gcc6/gcc-4.9-musl-fortify.patch new file mode 100644 index 000000000..daae954c8 --- /dev/null +++ b/legacy/gcc6/gcc-4.9-musl-fortify.patch @@ -0,0 +1,11 @@ +--- gcc-4.9.2/gcc/config/linux.h.orig 2015-03-09 13:27:13.289736710 +0000 ++++ gcc-4.9.2/gcc/config/linux.h 2015-03-09 13:29:32.295625046 +0000 +@@ -146,6 +146,8 @@ + + #ifdef NATIVE_SYSTEM_HEADER_DIR + #define INCLUDE_DEFAULTS_MUSL_NATIVE \ ++ { NATIVE_SYSTEM_HEADER_DIR "/fortify", 0, 0, 0, 1, 2 }, \ ++ { NATIVE_SYSTEM_HEADER_DIR "/fortify", 0, 0, 0, 1, 0 }, \ + { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 2 }, \ + { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 0 }, + #else diff --git a/legacy/gcc6/gcc-5.4.0-locale.patch b/legacy/gcc6/gcc-5.4.0-locale.patch new file mode 100644 index 000000000..dca3ba9e8 --- /dev/null +++ b/legacy/gcc6/gcc-5.4.0-locale.patch @@ -0,0 +1,13 @@ +diff --git gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc.orig gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc +--- gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc.orig ++++ gcc-5.4.0/libstdc++-v3/config/locale/generic/c_locale.cc +@@ -213,9 +213,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + // Currently, the generic model only supports the "C" locale. + // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html + __cloc = 0; +- if (strcmp(__s, "C")) +- __throw_runtime_error(__N("locale::facet::_S_create_c_locale " +- "name not valid")); + } + + void diff --git a/legacy/gcc6/gcc-6.1-musl-libssp.patch b/legacy/gcc6/gcc-6.1-musl-libssp.patch new file mode 100644 index 000000000..fe5c61434 --- /dev/null +++ b/legacy/gcc6/gcc-6.1-musl-libssp.patch @@ -0,0 +1,20 @@ +Author: Timo Teräs <timo.teras@iki.fi> + +Alpine musl package provides libssp_nonshared.a. We link to it unconditionally, +as otherwise we get link failures if some objects are -fstack-protector built +and final link happens with -fno-stack-protector. This seems to be the common +case when bootstrapping gcc, the piepatches do not seem to fully fix the +crosstoolchain and bootstrap sequence wrt. stack-protector flag usage. + +--- gcc-6.1.0/gcc/gcc.c.orig ++++ gcc-6.1.0/gcc/gcc.c +@@ -870,8 +870,7 @@ + + #ifndef LINK_SSP_SPEC + #ifdef TARGET_LIBC_PROVIDES_SSP +-#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \ +- "|fstack-protector-strong|fstack-protector-explicit:}" ++#define LINK_SSP_SPEC "-lssp_nonshared" + #else + #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \ + "|fstack-protector-strong|fstack-protector-explicit" \ diff --git a/legacy/gcc6/gcc-pure64.patch b/legacy/gcc6/gcc-pure64.patch new file mode 100644 index 000000000..2c350fe5a --- /dev/null +++ b/legacy/gcc6/gcc-pure64.patch @@ -0,0 +1,89 @@ +--- ./gcc/config/i386/t-linux64.orig 2013-01-14 16:32:37.000000000 +0000 ++++ ./gcc/config/i386/t-linux64 2013-04-22 06:12:32.984439677 +0000 +@@ -34,6 +34,6 @@ + comma=, + MULTILIB_OPTIONS = $(subst $(comma),/,$(TM_MULTILIB_CONFIG)) + MULTILIB_DIRNAMES = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS))) +-MULTILIB_OSDIRNAMES = m64=../lib64$(call if_multiarch,:x86_64-linux-gnu) +-MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:i386-linux-gnu) ++MULTILIB_OSDIRNAMES = m64=../lib ++MULTILIB_OSDIRNAMES+= m32=../lib32 + MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-linux-gnux32) +--- ./gcc/config/aarch64/t-aarch64-linux.orig ++++ ./gcc/config/aarch64/t-aarch64-linux +@@ -22,7 +22,7 @@ + LIB1ASMFUNCS = _aarch64_sync_cache_range + + AARCH_BE = $(if $(findstring TARGET_BIG_ENDIAN_DEFAULT=1, $(tm_defines)),_be) +-MULTILIB_OSDIRNAMES = mabi.lp64=../lib64$(call if_multiarch,:aarch64$(AARCH_BE)-linux-gnu) ++MULTILIB_OSDIRNAMES = mabi.lp64=../lib + MULTIARCH_DIRNAME = $(call if_multiarch,aarch64$(AARCH_BE)-linux-gnu) + + MULTILIB_OSDIRNAMES += mabi.ilp32=../libilp32 +--- ./gcc/config/s390/t-linux64.orig ++++ ./gcc/config/s390/t-linux64 +@@ -7,5 +7,5 @@ + MULTILIB_OPTIONS = m64/m31 + MULTILIB_DIRNAMES = 64 32 +-MULTILIB_OSDIRNAMES = ../lib64$(call if_multiarch,:s390x-linux-gnu) +-MULTILIB_OSDIRNAMES += $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:s390-linux-gnu) ++MULTILIB_OSDIRNAMES = m64=../lib ++MULTILIB_OSDIRNAMES+= m32=../lib32 + +--- ./gcc/config/rs6000/t-linux.orig ++++ ./gcc/config/rs6000/t-linux +@@ -2,7 +2,8 @@ + # or soft-float. + ifeq (,$(filter $(with_cpu),$(SOFT_FLOAT_CPUS))$(findstring soft,$(with_float))) + ifneq (,$(findstring powerpc64,$(target))) +-MULTILIB_OSDIRNAMES := .=../lib64$(call if_multiarch,:powerpc64-linux-gnu) ++MULTILIB_OSDIRNAMES := m64=../lib ++MULTILIB_OSDIRNAMES += m32=../lib32 + else + ifneq (,$(findstring spe,$(target))) + MULTIARCH_DIRNAME := powerpc-linux-gnuspe$(if $(findstring 8548,$(with_cpu)),,v1) +@@ -14,7 +15,8 @@ + MULTIARCH_DIRNAME := $(subst -linux,le-linux,$(MULTIARCH_DIRNAME)) + endif + ifneq (,$(findstring powerpc64le,$(target))) +-MULTILIB_OSDIRNAMES := $(subst -linux,le-linux,$(MULTILIB_OSDIRNAMES)) ++MULTILIB_OSDIRNAMES := m64=../lib ++MULTILIB_OSDIRNAMES += m32=../lib32 + endif + endif + +--- ./gcc/config/rs6000/t-linux64.orig ++++ ./gcc/config/rs6000/t-linux64 +@@ -28,8 +28,8 @@ + MULTILIB_OPTIONS := m64/m32 + MULTILIB_DIRNAMES := 64 32 + MULTILIB_EXTRA_OPTS := +-MULTILIB_OSDIRNAMES := m64=../lib64$(call if_multiarch,:powerpc64-linux-gnu) +-MULTILIB_OSDIRNAMES += m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:powerpc-linux-gnu) ++MULTILIB_OSDIRNAMES := m64=../lib ++MULTILIB_OSDIRNAMES += m32=../lib32 + + rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c + $(COMPILE) $< +--- ./gcc/config/rs6000/t-linux64bele.orig ++++ ./gcc/config/rs6000/t-linux64bele +@@ -2,6 +2,6 @@ + + MULTILIB_OPTIONS += mlittle + MULTILIB_DIRNAMES += le +-MULTILIB_OSDIRNAMES += $(subst =,.mlittle=,$(subst lible32,lib32le,$(subst lible64,lib64le,$(subst lib,lible,$(subst -linux,le-linux,$(MULTILIB_OSDIRNAMES)))))) +-MULTILIB_OSDIRNAMES += $(subst $(if $(findstring 64,$(target)),m64,m32).,,$(filter $(if $(findstring 64,$(target)),m64,m32).mlittle%,$(MULTILIB_OSDIRNAMES))) ++MULTILIB_OSDIRNAMES = m64=../lib ++MULTILIB_OSDIRNAMES+= m32=../lib32 + MULTILIB_MATCHES := ${MULTILIB_MATCHES_ENDIAN} +--- ./gcc/config/rs6000/t-linux64lebe.orig ++++ ./gcc/config/rs6000/t-linux64lebe +@@ -2,6 +2,6 @@ + + MULTILIB_OPTIONS += mbig + MULTILIB_DIRNAMES += be +-MULTILIB_OSDIRNAMES += $(subst =,.mbig=,$(subst libbe32,lib32be,$(subst libbe64,lib64be,$(subst lib,libbe,$(subst le-linux,-linux,$(MULTILIB_OSDIRNAMES)))))) +-MULTILIB_OSDIRNAMES += $(subst $(if $(findstring 64,$(target)),m64,m32).,,$(filter $(if $(findstring 64,$(target)),m64,m32).mbig%,$(MULTILIB_OSDIRNAMES))) ++MULTILIB_OSDIRNAMES := m64=../lib ++MULTILIB_OSDIRNAMES += m32=../lib32 + MULTILIB_MATCHES := ${MULTILIB_MATCHES_ENDIAN} diff --git a/legacy/gcc6/isl-fix.patch b/legacy/gcc6/isl-fix.patch new file mode 100644 index 000000000..d8d294c0e --- /dev/null +++ b/legacy/gcc6/isl-fix.patch @@ -0,0 +1,15 @@ +Fix build with isl >= 0.20. + +Backport from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86724 + +--- gcc-6.4.0/gcc/graphite.h.old 2016-01-25 18:19:20.909140000 -0600 ++++ gcc-6.4.0/gcc/graphite.h 2022-06-21 02:51:53.660000000 -0500 +@@ -40,6 +40,8 @@ + #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS + /* isl 0.15 or later. */ + #include <isl/schedule_node.h> ++#include <isl/id.h> ++#include <isl/space.h> + + #else + /* isl 0.14 or 0.13. */ diff --git a/legacy/gcc6/libgcc-always-build-gcceh.a.patch b/legacy/gcc6/libgcc-always-build-gcceh.a.patch new file mode 100644 index 000000000..74ae89730 --- /dev/null +++ b/legacy/gcc6/libgcc-always-build-gcceh.a.patch @@ -0,0 +1,39 @@ +Highly inspired by: + http://landley.net/hg/aboriginal/file/7e0747a665ab/sources/patches/gcc-core-libgcceh.patch + +diff -durN gcc-4.6.0.orig/libgcc/Makefile.in gcc-4.6.0/libgcc/Makefile.in +--- gcc-4.6.0.orig/libgcc/Makefile.in 2011-01-26 05:19:58.000000000 +0100 ++++ gcc-4.6.0/libgcc/Makefile.in 2011-09-12 18:17:12.743718974 +0200 +@@ -772,8 +772,9 @@ + libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT) + endif + ++all: libgcc_eh.a + ifeq ($(enable_shared),yes) +-all: libgcc_eh.a libgcc_s$(SHLIB_EXT) ++all: libgcc_s$(SHLIB_EXT) + ifneq ($(LIBUNWIND),) + all: libunwind$(SHLIB_EXT) + endif +@@ -950,10 +951,6 @@ + install-shared: + $(mkinstalldirs) $(DESTDIR)$(inst_libdir) + +- $(INSTALL_DATA) libgcc_eh.a $(DESTDIR)$(inst_libdir)/ +- chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a +- $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a +- + $(subst @multilib_dir@,$(MULTIDIR),$(subst \ + @shlib_base_name@,libgcc_s,$(subst \ + @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL)))) +@@ -968,6 +965,10 @@ + chmod 644 $(DESTDIR)$(inst_libdir)/libgcov.a + $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcov.a + ++ $(INSTALL_DATA) libgcc_eh.a $(DESTDIR)$(inst_libdir)/ ++ chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a ++ $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a ++ + parts="$(INSTALL_PARTS)"; \ + for file in $$parts; do \ + rm -f $(DESTDIR)$(inst_libdir)/$$file; \ diff --git a/legacy/gcc6/libgo-musl-1.2.3.patch b/legacy/gcc6/libgo-musl-1.2.3.patch new file mode 100644 index 000000000..8873d44eb --- /dev/null +++ b/legacy/gcc6/libgo-musl-1.2.3.patch @@ -0,0 +1,13 @@ +diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh +index 6fef104..06289a4 100755 +--- a/libgo/mksysinfo.sh ++++ b/libgo/mksysinfo.sh +@@ -355,7 +355,7 @@ if ! grep '^const SIGCLD ' ${OUT} >/dev/null 2>&1; then + fi + + # The syscall numbers. We force the names to upper case. +-grep '^const _SYS_' gen-sysinfo.go | \ ++grep '^const _SYS_[a-z]' gen-sysinfo.go | \ + sed -e 's/const _\(SYS_[^= ]*\).*$/\1/' | \ + while read sys; do + sup=`echo $sys | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` diff --git a/legacy/gcc6/lra-pentium.patch b/legacy/gcc6/lra-pentium.patch new file mode 100644 index 000000000..e876bcc39 --- /dev/null +++ b/legacy/gcc6/lra-pentium.patch @@ -0,0 +1,48 @@ +--- trunk/gcc/lra-assigns.c 2017/03/10 20:53:18 246058 ++++ trunk/gcc/lra-assigns.c 2017/03/10 21:17:13 246059 +@@ -889,6 +889,30 @@ + live_pseudos_reg_renumber[regno] = hard_regno; + } + ++/* Return true iff there is a reason why pseudo SPILL_REGNO should not ++ be spilled. */ ++static bool ++must_not_spill_p (unsigned spill_regno) ++{ ++ if ((pic_offset_table_rtx != NULL ++ && spill_regno == REGNO (pic_offset_table_rtx)) ++ || ((int) spill_regno >= lra_constraint_new_regno_start ++ && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno) ++ && ! bitmap_bit_p (&lra_split_regs, spill_regno) ++ && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno) ++ && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))) ++ return true; ++ /* A reload pseudo that requires a singleton register class should ++ not be spilled. ++ FIXME: this mitigates the issue on certain i386 patterns, but ++ does not solve the general case where existing reloads fully ++ cover a limited register class. */ ++ if (!bitmap_bit_p (&non_reload_pseudos, spill_regno) ++ && reg_class_size [reg_preferred_class (spill_regno)] == 1) ++ return true; ++ return false; ++} ++ + /* Array used for sorting reload pseudos for subsequent allocation + after spilling some pseudo. */ + static int *sorted_reload_pseudos; +@@ -960,13 +984,7 @@ + /* Spill pseudos. */ + static_p = false; + EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi) +- if ((pic_offset_table_rtx != NULL +- && spill_regno == REGNO (pic_offset_table_rtx)) +- || ((int) spill_regno >= lra_constraint_new_regno_start +- && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno) +- && ! bitmap_bit_p (&lra_split_regs, spill_regno) +- && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno) +- && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))) ++ if (must_not_spill_p (spill_regno)) + goto fail; + else if (non_spilled_static_chain_regno_p (spill_regno)) + static_p = true; diff --git a/legacy/glfw/APKBUILD b/legacy/glfw/APKBUILD deleted file mode 100644 index ab55f9771..000000000 --- a/legacy/glfw/APKBUILD +++ /dev/null @@ -1,48 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=glfw -pkgver=3.2.1 -pkgrel=0 -pkgdesc="OpenGL desktop development library" -url="http://www.glfw.org/" -arch="all" -options="!check" # Tests require X11, GL, and manual intervention. -license="Zlib" -depends="" -depends_dev="mesa-dev" -makedepends="$depends_dev cmake doxygen libx11-dev libxrandr-dev libxcursor-dev - libxinerama-dev" -subpackages="$pkgname-dev $pkgname-doc" -source="https://github.com/glfw/glfw/releases/download/3.2.1/glfw-$pkgver.zip" - -build() { - cd "$builddir" - if [ "$CBUILD" != "$CHOST" ]; then - CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" - fi - cmake \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DBUILD_SHARED_LIBS=True \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - -DBUILD_SHARED_LIBS=ON \ - -DGLFW_BUILD_TESTS=OFF \ - -DGLFW_BUILD_EXAMPLES=OFF \ - ${CMAKE_CROSSOPTS} - make -} - -check() { - cd "$builddir" - CTEST_OUTPUT_ON_FAILURE=TRUE ctest -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install - install -D -d "$builddir"/docs/html "$pkgdir"/usr/share/doc/$pkgname/ -} - -sha512sums="73dd6d4a8d28a2b423f0fb25489659c1a845182b7ef09848d4f442cdc489528aea90f43ac84aeedb9d2301c4487f39782b647ee4959e67e83babb838372b980c glfw-3.2.1.zip" diff --git a/legacy/heimdal/CVE-2017-17439.patch b/legacy/heimdal/CVE-2017-17439.patch deleted file mode 100644 index 8c3273971..000000000 --- a/legacy/heimdal/CVE-2017-17439.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 749d377fa357351a7bbba51f8aae72cdf0629592 Mon Sep 17 00:00:00 2001 -From: Viktor Dukhovni <viktor@twosigma.com> -Date: Tue, 5 Dec 2017 18:49:50 -0500 -Subject: [PATCH] Security: Avoid NULL structure pointer member dereference - -This can happen in the error path when processing malformed AS -requests with a NULL client name. Bug originally introduced on -Fri Feb 13 09:26:01 2015 +0100 in commit: - - a873e21d7c06f22943a90a41dc733ae76799390d - - kdc: base _kdc_fast_mk_error() on krb5_mk_error_ext() - -Original patch by Jeffrey Altman <jaltman@secure-endpoints.com> - -(cherry picked from commit 1a6a6e462dc2ac6111f9e02c6852ddec4849b887) ---- - kdc/kerberos5.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c -index 95a74927f7..675b406b82 100644 ---- a/kdc/kerberos5.c -+++ b/kdc/kerberos5.c -@@ -2226,15 +2226,17 @@ _kdc_as_rep(kdc_request_t r, - /* - * In case of a non proxy error, build an error message. - */ -- if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) { -+ if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) { - ret = _kdc_fast_mk_error(context, r, - &error_method, - r->armor_crypto, - &req->req_body, - ret, r->e_text, - r->server_princ, -- &r->client_princ->name, -- &r->client_princ->realm, -+ r->client_princ ? -+ &r->client_princ->name : NULL, -+ r->client_princ ? -+ &r->client_princ->realm : NULL, - NULL, NULL, - reply); - if (ret) diff --git a/legacy/hwids/APKBUILD b/legacy/hwids/APKBUILD new file mode 100644 index 000000000..183bda57d --- /dev/null +++ b/legacy/hwids/APKBUILD @@ -0,0 +1,67 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=hwids +pkgver=20200306 +pkgrel=0 +pkgdesc="Hardware identification databases" +url="https://github.com/gentoo/hwids/" +arch="noarch" +options="!check" # No test suite, just databases. +license="BSD-3-Clause OR GPL-2.0+" +subpackages="$pkgname-net $pkgname-pci $pkgname-udev $pkgname-usb" +depends="$subpackages" +makedepends="eudev-dev" +subpackages="$subpackages $pkgname-doc" +source="https://github.com/gentoo/hwids/archive/hwids-$pkgver.tar.gz" +builddir="$srcdir/hwids-hwids-$pkgver" + +build() { + make UDEV=yes +} + +package() { + make DESTDIR="$pkgdir" DOCDIR="/usr/share/doc/$pkgname-$pkgver" \ + MISCDIR="/usr/share/hwdata" UDEV=yes install +} + +_mv() { + pkgdesc="$pkgdesc ($1)" + shift + depends="" + mkdir -p "$subpkgdir"/usr/share/hwdata + for _file in $*; do + mv "$pkgdir"/usr/share/hwdata/$_file "$subpkgdir"/usr/share/hwdata + done +} + +usb() { + replaces="hwdata-usb" + provides="hwdata-usb=$pkgver-r$pkgrel" + _mv "USB IDs" usb.ids +} + +pci() { + replaces="hwdata-pci" + provides="hwdata-pci=$pkgver-r$pkgrel" + _mv "PCI IDs" pci.ids +} + +net() { + replaces="hwdata-oui" + provides="hwdata-oui=$pkgver-r$pkgrel" + license="Public-Domain" + _mv "Networking OUIs" oui.txt iab.txt +} + +udev() { + install_if="hwids=$pkgver-r$pkgrel eudev" + install_if="hwids-pci=$pkgver-r$pkgrel eudev" + install_if="hwids-usb=$pkgver-r$pkgrel eudev" + pkgdesc="$pkgdesc (udev integration)" + + mkdir -p "$subpkgdir"/ + mv "$pkgdir"/lib "$subpkgdir"/ + mv "$pkgdir"/etc "$subpkgdir"/ +} + +sha512sums="eff1d2783925ca459b387fbaa5cf68a98aa4209ab8509ad92a902b4d02cc7f4a47e5506c2beed4c792d24a8ab636ad77b376a92b59ae4f605d1b5258350ff250 hwids-20200306.tar.gz" diff --git a/legacy/ikona/APKBUILD b/legacy/ikona/APKBUILD new file mode 100644 index 000000000..c70ad2e59 --- /dev/null +++ b/legacy/ikona/APKBUILD @@ -0,0 +1,71 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=ikona +pkgver=1.0 +pkgrel=0 +pkgdesc="Icon preview utility" +url="https://kde.org/applications/graphics/org.kde.Ikona" +arch="all" +license="GPL-2.0+" +depends="" +makedepends="qt5-qtbase-dev qt5-qtdeclarative-dev cmake extra-cmake-modules + kconfigwidgets-dev ki18n-dev kirigami2-dev rust cargo + cairo-dev gdk-pixbuf-dev pango-dev" +subpackages="$pkgname-lang $pkgname-bash-completion:bashcomp:noarch + $pkgname-fish-completion:fishcomp:noarch + $pkgname-zsh-completion:zshcomp:noarch" +source="https://download.kde.org/stable/ikona/$pkgver/ikona-$pkgver.tar.xz + https://download.kde.org/stable/ikona/1.0/ikona-1.0.cargo.vendor.tar.xz + " + +unpack() { + default_unpack + mv "$srcdir"/ikona-1.0.cargo.vendor.tar.xz \ + "$builddir"/ikona.cargo.vendor.tar.xz +} + +build() { + if [ "$CBUILD" != "$CHOST" ]; then + CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" + fi + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DCMAKE_INSTALL_SYSCONFDIR=/etc \ + -DBUILD_SHARED_LIBS=True \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ + -DCMAKE_C_FLAGS="$CFLAGS" \ + ${CMAKE_CROSSOPTS} \ + . + make +} + +check() { + CTEST_OUTPUT_ON_FAILURE=TRUE ctest +} + +package() { + make DESTDIR="$pkgdir" install +} + +bashcomp() { + pkgdesc="$pkgdesc (Bash completions)" + mkdir -p "$subpkgdir"/etc + mv "$pkgdir"/etc/bash_completion.d "$subpkgdir"/etc/ +} + +fishcomp() { + pkgdesc="$pkgdesc (Fish completions)" + mkdir -p "$subpkgdir"/usr/share + mv "$pkgdir"/usr/share/fish "$subpkgdir"/usr/share/ +} + +zshcomp() { + pkgdesc="$pkgdesc (Z shell completions)" + mkdir -p "$subpkgdir"/usr/share + mv "$pkgdir"/usr/share/zsh "$subpkgdir"/usr/share/ +} + +sha512sums="30bde3f3b062ccf661ee8950c762412a6b9eebff625216641607cbae7f7f8123702c231cbce82acfb666a8b69c863e4b22e8daf79d1541b7c70781189ffee144 ikona-1.0.tar.xz +3bca0c7b66e603e7e06e0ac30c0cdb3d8c3baa812e600f322ef56a0be1692e57cc39348f1c40fdcfe07da6d4b624604cec0003f0d7e1be419462fff5832cd301 ikona-1.0.cargo.vendor.tar.xz" diff --git a/legacy/java-gcj-compat/APKBUILD b/legacy/java-gcj-compat/APKBUILD index a75f1e6b1..7363e854f 100644 --- a/legacy/java-gcj-compat/APKBUILD +++ b/legacy/java-gcj-compat/APKBUILD @@ -1,4 +1,4 @@ -# Contributor: Timo Teras <timo.teras@iki.fi> +# Contributor: Timo Teräs <timo.teras@iki.fi> # Maintainer: A. Wilcox <awilfox@adelielinux.org> gccver=6.4.0 gccpkgrel=10 diff --git a/legacy/kalarmcal/build-with-kf5-kholidays.patch b/legacy/kalarmcal/build-with-kf5-kholidays.patch deleted file mode 100644 index 0d5bd88f8..000000000 --- a/legacy/kalarmcal/build-with-kf5-kholidays.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- kalarmcal-17.12.2/CMakeLists.txt.old 2018-02-06 00:37:47.000000000 +0000 -+++ kalarmcal-17.12.2/CMakeLists.txt 2018-03-04 22:17:25.340681117 +0000 -@@ -26,7 +26,7 @@ - set(KALARM_LIB_VERSION ${PIM_VERSION}) - - set(CALENDARCORE_LIB_VERSION "5.7.2") --set(HOLIDAY_LIB_VERSION "5.7.2") -+set(HOLIDAY_LIB_VERSION "5.6.2") - set(IDENTITYMANAGER_LIB_VERSION "5.7.2") - set(AKONADI_LIB_VERSION "5.7.2") - ecm_setup_version(PROJECT VARIABLE_PREFIX KALARMCAL diff --git a/legacy/kidentitymanagement/APKBUILD b/legacy/kidentitymanagement/APKBUILD deleted file mode 100644 index 9f3e7cfb1..000000000 --- a/legacy/kidentitymanagement/APKBUILD +++ /dev/null @@ -1,45 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=kidentitymanagement -pkgver=18.04.3 -pkgrel=0 -pkgdesc="Library for managing user identities" -url="https://www.kde.org/" -arch="all" -license="LGPL-2.1" -options="!check" # Test requires X11 desktop running. -depends="" -depends_dev="qt5-qtbase-dev kcoreaddons-dev kcompletion-dev ktextwidgets-dev - kxmlgui-dev kio-dev kconfig-dev kcodecs-dev kiconthemes-dev - kpimtextedit-dev" -makedepends="$depends_dev cmake extra-cmake-modules" -subpackages="$pkgname-dev $pkgname-lang" -source="https://download.kde.org/stable/applications/$pkgver/src/kidentitymanagement-$pkgver.tar.xz" - -build() { - cd "$builddir" - if [ "$CBUILD" != "$CHOST" ]; then - CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" - fi - cmake \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DBUILD_SHARED_LIBS=True \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - ${CMAKE_CROSSOPTS} - make -} - -check() { - cd "$builddir" - CTEST_OUTPUT_ON_FAILURE=TRUE ctest -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -sha512sums="4e6ad309d18e2bb88a86a1b236bb29782aede0ca18cc5e4ac76926e17030ec6367d80fda50dab4c29fcf5a4475560e027edbb7cc9cdedf2c3d6f9dba7ff6697b kidentitymanagement-18.04.3.tar.xz" diff --git a/legacy/kimap/APKBUILD b/legacy/kimap/APKBUILD deleted file mode 100644 index 5e75e20c3..000000000 --- a/legacy/kimap/APKBUILD +++ /dev/null @@ -1,43 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=kimap -pkgver=18.04.3 -pkgrel=0 -pkgdesc="IMAP framework for KDE" -url="https://www.kde.org/" -arch="all" -license="GPL-2.0" -depends="" -depends_dev="qt5-qtbase-dev kcoreaddons-dev ki18n-dev kmime-dev cyrus-sasl-dev - kio-dev" -makedepends="$depends_dev cmake extra-cmake-modules" -subpackages="$pkgname-dev $pkgname-lang" -source="https://download.kde.org/stable/applications/$pkgver/src/kimap-$pkgver.tar.xz" - -build() { - cd "$builddir" - if [ "$CBUILD" != "$CHOST" ]; then - CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" - fi - cmake \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DBUILD_SHARED_LIBS=True \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - ${CMAKE_CROSSOPTS} - make -} - -check() { - cd "$builddir" - CTEST_OUTPUT_ON_FAILURE=TRUE ctest -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -sha512sums="a17e4132a3c0d698eda715fa7ebcc5d7d4e16b9ad8aefab25bc3d91a64200504fdfcf034d42929f56c0b26ee90ad8b068e58b7bac1d2a3934ae5757de4c3b966 kimap-18.04.3.tar.xz" diff --git a/legacy/kmailtransport/APKBUILD b/legacy/kmailtransport/APKBUILD new file mode 100644 index 000000000..dc531b704 --- /dev/null +++ b/legacy/kmailtransport/APKBUILD @@ -0,0 +1,46 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=kmailtransport +pkgver=20.08.1 +pkgrel=0 +pkgdesc="KDE email transport library" +url="https://kde.org/" +arch="all" +license="LGPL-2.1+" +depends="" +makedepends="qt5-qtbase-dev cmake extra-cmake-modules kcmutils-dev kmime-dev + kwallet-dev akonadi-dev akonadi-mime-dev ksmtp-dev" +subpackages="$pkgname-dev $pkgname-lang" +source="https://download.kde.org/stable/release-service/$pkgver/src/kmailtransport-$pkgver.tar.xz + degoogled.patch + " + +build() { + if [ "$CBUILD" != "$CHOST" ]; then + CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" + fi + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DBUILD_SHARED_LIBS=True \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ + -DCMAKE_C_FLAGS="$CFLAGS" \ + ${CMAKE_CROSSOPTS} \ + . + make +} + +check() { + # Akonadi tests require D-Bus. + export XDG_RUNTIME_DIR=$(mktemp -d) + QT_QPA_PLATFORM=offscreen CTEST_OUTPUT_ON_FAILURE=TRUE ctest -E 'akonadi-*' + rm -fr "${XDG_RUNTIME_DIR}" +} + +package() { + make DESTDIR="$pkgdir" install +} + +sha512sums="409475cf4a34b15f7f2bed4d5e7612c8c72e90cb39cc778ce79f1132180cde311a2d490e2172787c1461ca017348faff74fc10203aa482f51ef81550a15e310e kmailtransport-20.08.1.tar.xz +0fbde4a8983be652ee10cd1c64391240c80ccaae697c77c43f8c9bc0bfd85cbe0dd37a5fc6860185ed15575c8bfcd198276c8291bbfc83bb1811a57eea5ea6a7 degoogled.patch" diff --git a/legacy/kmailtransport/degoogled.patch b/legacy/kmailtransport/degoogled.patch new file mode 100644 index 000000000..52199c040 --- /dev/null +++ b/legacy/kmailtransport/degoogled.patch @@ -0,0 +1,222 @@ +diff -Naur kmailtransport-20.04.3/CMakeLists.txt kmailtransport-degoogled/CMakeLists.txt +--- kmailtransport-20.04.3/CMakeLists.txt 2020-07-18 22:38:18.572259714 +0000 ++++ kmailtransport-degoogled/CMakeLists.txt 2020-07-18 22:38:06.963507959 +0000 +@@ -29,7 +29,6 @@ + set(AKONADI_LIB_VERSION "5.15.1") + set(AKONADIMIME_LIB_VERSION "5.15.1") + set(KSMTP_LIB_VERSION "5.15.1") +-set(KGAPI_LIB_VERSION "5.15.1") + + set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5MailTransport") + +@@ -43,7 +42,6 @@ + find_package(KF5Akonadi ${AKONADI_LIB_VERSION} CONFIG REQUIRED) + find_package(KF5AkonadiMime ${AKONADIMIME_LIB_VERSION} CONFIG REQUIRED) + find_package(KPimSMTP ${KSMTP_LIB_VERSION} CONFIG REQUIRED) +-find_package(KPimGAPI ${KGAPI_LIB_VERSION} CONFIG REQUIRED) + + option(KDEPIM_RUN_AKONADI_TEST "Enable autotest based on Akonadi." TRUE) + if (EXISTS "${CMAKE_SOURCE_DIR}/.git") +diff -Naur kmailtransport-20.04.3/src/kmailtransport/mailtransport.kcfg kmailtransport-degoogled/src/kmailtransport/mailtransport.kcfg +--- kmailtransport-20.04.3/src/kmailtransport/mailtransport.kcfg 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/mailtransport.kcfg 2020-07-18 22:35:49.028339597 +0000 +@@ -79,7 +79,6 @@ + <choice name="APOP" /> + <choice name="CLEAR" /> + <choice name="ANONYMOUS" /> +- <choice name="XOAUTH2" /> + </choices> + <default>PLAIN</default> + </entry> +diff -Naur kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/CMakeLists.txt kmailtransport-degoogled/src/kmailtransport/plugins/smtp/CMakeLists.txt +--- kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/CMakeLists.txt 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/plugins/smtp/CMakeLists.txt 2020-07-18 22:37:43.696009823 +0000 +@@ -27,5 +27,4 @@ + KF5::ConfigWidgets + KF5::KIOWidgets + KPim::SMTP +- KPim::GAPICore + ) +diff -Naur kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/autotests/CMakeLists.txt kmailtransport-degoogled/src/kmailtransport/plugins/smtp/autotests/CMakeLists.txt +--- kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/autotests/CMakeLists.txt 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/plugins/smtp/autotests/CMakeLists.txt 2020-07-18 22:37:50.785247545 +0000 +@@ -15,6 +15,5 @@ + KF5::ConfigWidgets + KF5::KIOWidgets + KPim::SMTP +- KPim::GAPICore + TEST_NAME smtpjobtest + ) +diff -Naur kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp kmailtransport-degoogled/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp +--- kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp 2020-07-18 22:37:12.009416961 +0000 +@@ -70,8 +70,7 @@ + << Transport::EnumAuthenticationType::CRAM_MD5 + << Transport::EnumAuthenticationType::DIGEST_MD5 + << Transport::EnumAuthenticationType::NTLM +- << Transport::EnumAuthenticationType::GSSAPI +- << Transport::EnumAuthenticationType::XOAUTH2; ++ << Transport::EnumAuthenticationType::GSSAPI; + sslCapa = tlsCapa = noEncCapa; + updateAuthCapbilities(); + } +diff -Naur kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/smtpjob.cpp kmailtransport-degoogled/src/kmailtransport/plugins/smtp/smtpjob.cpp +--- kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/smtpjob.cpp 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/plugins/smtp/smtpjob.cpp 2020-07-18 22:37:25.447971965 +0000 +@@ -38,13 +38,6 @@ + #include <KSMTP/LoginJob> + #include <KSMTP/SendJob> + +-#include <KGAPI/Account> +-#include <KGAPI/AuthJob> +-#include <KGAPI/AccountManager> +- +-#define GOOGLE_API_KEY QStringLiteral("554041944266.apps.googleusercontent.com") +-#define GOOGLE_API_SECRET QStringLiteral("mdT1DjzohxN3npUUzkENT0gO") +- + using namespace MailTransport; + + class SessionPool +@@ -196,50 +189,9 @@ + return; + } + +- if (transport()->authenticationType() == TransportBase::EnumAuthenticationType::XOAUTH2) { +- auto promise = KGAPI2::AccountManager::instance()->findAccount( +- GOOGLE_API_KEY, transport()->userName(), { KGAPI2::Account::mailScopeUrl() }); +- connect(promise, &KGAPI2::AccountPromise::finished, +- this, [forceRefresh, this](KGAPI2::AccountPromise *promise) { +- if (promise->account()) { +- if (forceRefresh) { +- promise = KGAPI2::AccountManager::instance()->refreshTokens( +- GOOGLE_API_KEY, GOOGLE_API_SECRET, transport()->userName()); +- } else { +- onTokenRequestFinished(promise); +- return; +- } +- } else { +- promise = KGAPI2::AccountManager::instance()->getAccount( +- GOOGLE_API_KEY, GOOGLE_API_SECRET, transport()->userName(), +- { KGAPI2::Account::mailScopeUrl() }); +- } +- connect(promise, &KGAPI2::AccountPromise::finished, +- this, &SmtpJob::onTokenRequestFinished); +- }); +- } else { +- startLoginJob(); +- } +-} +- +-void SmtpJob::onTokenRequestFinished(KGAPI2::AccountPromise *promise) +-{ +- if (promise->hasError()) { +- qCWarning(MAILTRANSPORT_SMTP_LOG) << "Error obtaining XOAUTH2 token:" << promise->errorText(); +- setError(KJob::UserDefinedError); +- setErrorText(promise->errorText()); +- emitResult(); +- return; +- } +- +- const auto account = promise->account(); +- const QString tokens = QStringLiteral("%1\001%2").arg(account->accessToken(), +- account->refreshToken()); +- transport()->setPassword(tokens); + startLoginJob(); + } + +- + void SmtpJob::startLoginJob() + { + if (!transport()->requiresAuthentication()) { +@@ -281,11 +233,7 @@ + } + } + +- if (transport()->authenticationType() == Transport::EnumAuthenticationType::XOAUTH2) { +- passwd = passwd.left(passwd.indexOf(QLatin1Char('\001'))); +- } else { +- passwd = transport()->password(); +- } ++ passwd = transport()->password(); + login->setUserName(transport()->userName()); + login->setPassword(passwd); + switch (transport()->authenticationType()) { +@@ -298,9 +246,6 @@ + case TransportBase::EnumAuthenticationType::CRAM_MD5: + login->setPreferedAuthMode(KSmtp::LoginJob::CramMD5); + break; +- case TransportBase::EnumAuthenticationType::XOAUTH2: +- login->setPreferedAuthMode(KSmtp::LoginJob::XOAuth2); +- break; + case TransportBase::EnumAuthenticationType::DIGEST_MD5: + login->setPreferedAuthMode(KSmtp::LoginJob::DigestMD5); + break; +diff -Naur kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/smtpjob.h kmailtransport-degoogled/src/kmailtransport/plugins/smtp/smtpjob.h +--- kmailtransport-20.04.3/src/kmailtransport/plugins/smtp/smtpjob.h 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/plugins/smtp/smtpjob.h 2020-07-18 22:37:38.056616206 +0000 +@@ -31,10 +31,6 @@ + class Slave; + } + +-namespace KGAPI2 { +-class AccountPromise; +-} +- + class SmtpJobPrivate; + + namespace MailTransport { +@@ -74,7 +70,6 @@ + + private: + void startPasswordRetrieval(bool forceRefresh = false); +- void onTokenRequestFinished(KGAPI2::AccountPromise *result); + void startSmtpJob(); + void startLoginJob(); + void startSendJob(); +diff -Naur kmailtransport-20.04.3/src/kmailtransport/servertest.cpp kmailtransport-degoogled/src/kmailtransport/servertest.cpp +--- kmailtransport-20.04.3/src/kmailtransport/servertest.cpp 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/servertest.cpp 2020-07-18 22:36:05.166604311 +0000 +@@ -80,10 +80,6 @@ + bool handleNntpConversation(MailTransport::Socket *socket, int type, int *stage, const QString &response, bool *shouldStartTLS); + QVector<int> parseAuthenticationList(const QStringList &authentications); + +- inline bool isGmail(const QString &server) const { +- return server.endsWith(QLatin1String("gmail.com")) || server.endsWith(QLatin1String("googlemail.com")); +- } +- + // slots + void slotNormalPossible(); + void slotNormalNotPossible(); +@@ -156,10 +152,6 @@ + result << Transport::EnumAuthenticationType::GSSAPI; + } else if (current == QLatin1String("ANONYMOUS")) { + result << Transport::EnumAuthenticationType::ANONYMOUS; +- } else if (current == QLatin1String("XOAUTH2")) { +- if (isGmail(server)) { +- result << Transport::EnumAuthenticationType::XOAUTH2; +- } + } + // APOP is handled by handlePopConversation() + } +@@ -183,9 +175,6 @@ + } + + QStringList protocols; +- if (isGmail(server)) { +- protocols << QStringLiteral("XOAUTH2"); +- } + + protocols << QStringLiteral("LOGIN") + << QStringLiteral("PLAIN") << QStringLiteral("CRAM-MD5") +diff -Naur kmailtransport-20.04.3/src/kmailtransport/transport.cpp kmailtransport-degoogled/src/kmailtransport/transport.cpp +--- kmailtransport-20.04.3/src/kmailtransport/transport.cpp 2020-06-18 06:30:31.000000000 +0000 ++++ kmailtransport-degoogled/src/kmailtransport/transport.cpp 2020-07-18 22:35:40.749229818 +0000 +@@ -142,8 +142,6 @@ + return QStringLiteral("APOP"); + case EnumAuthenticationType::ANONYMOUS: + return i18nc("Authentication method", "Anonymous"); +- case EnumAuthenticationType::XOAUTH2: +- return QStringLiteral("XOAUTH2"); + } + Q_ASSERT(false); + return QString(); diff --git a/legacy/libindicator/APKBUILD b/legacy/libindicator/APKBUILD new file mode 100644 index 000000000..5abb7b717 --- /dev/null +++ b/legacy/libindicator/APKBUILD @@ -0,0 +1,40 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=libindicator +pkgver=16.10 +pkgrel=0 +pkgdesc="Library for builidng indicators for applets" +url="https://launchpad.net/libindicator" +arch="all" +options="!check" # broken tests +license="GPL-3.0-only" +depends="" +makedepends="gtk+3.0-dev ido-dev autoconf automake libtool" +subpackages="$pkgname-dev" +source="https://distfiles.adelielinux.org/source/upstream/$pkgname-$pkgver.tar.gz" + +prepare() { + default_prepare + autoreconf -vif +} + +build() { + CFLAGS="-Wno-error" ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var + make +} + +check() { + make check +} + +package() { + make DESTDIR="$pkgdir" -j1 install +} + +sha512sums="451aca0a2bd127bb49cc5b01f4cf1a33d85c3618257e822a16f29774f7eba919fbeca9515e5cb6c5e15bf315d20335ad5742d197cf561d2442891c1552de62a3 libindicator-16.10.tar.gz" diff --git a/legacy/libreoffice/APKBUILD b/legacy/libreoffice/APKBUILD new file mode 100644 index 000000000..29ec4c2d3 --- /dev/null +++ b/legacy/libreoffice/APKBUILD @@ -0,0 +1,495 @@ +# Contributor: Jens Staal <staal1978@gmail.com> +# Contributor: Timo Teräs <timo.teras@iki.fi> +# Maintainer: Max Rees <maxcrees@me.com> + +# You probably don't want "srcdir", "pkgdir", or "deps" in CLEANUP, +# and you definitely don't want "deps" in ERROR_CLEANUP. +# Just "abuild clean undeps" once you're completely done. +# +# Even with JOBS=4 you're gonna want at least 8 GB of RAM. +# +# * Disk space: +# * Dependencies: 1557 MiB = 1.5 GiB +# * Downloads: 515 MiB +# * Subtotal: 2072 MiB = 2.0 GiB +# * Complete src: 34134 MiB +# * Complete pkg: 9399 MiB +# * All APKs: 2282 MiB = 2.2 GiB +# * Subtotal: 45815 MiB = 44.7 GiB +# * Grand total: 47887 MiB = 46.8 GiB +# +# Build stats: +# * Run "abuild deps fetch" first. +# * time abuild -r +# +# * x86_64 Intel i7-4810MQ (4 core 2.8 GHz, turbo to 3.8 GHz, no HT) +# JOBS=4, 8 GB RAM +# abuild -r 29590.16s user 1077.69s system 340% cpu 2:30:13.12 total + +pkgname=libreoffice +pkgver=6.4.0.3 +pkgrel=0 +case "$pkgver" in +*.*.*.*) _ver="${pkgver%.*}";; +*.*.*) _ver="$pkgver";; +esac +pkgdesc="LibreOffice - Meta package for the full office suite" +url="https://www.libreoffice.org/" +# While the metapackage technically is empty and should be "noarch", there's +# no easy way to change this to noarch and then change all of the subpackages +# to have the correct arch. Setting $arch in a split function is forbidden, +# and $subpackages doesn't really support setting $arch to anything other than +# noarch. +arch="all" +options="" +license="MPL-2.0 AND Apache-2.0 AND MIT AND X11 AND (MPL-1.1 OR GPL-2.0+ OR LGPL-2.1+) AND GPL-2.0+ AND GPL-3.0 AND GPL-3.0+ AND LGPL-2.1 AND LGPL-3.0+ AND BSD-3-Clause AND SISSL AND IJG AND CC-BY-SA-3.0" + +depends="$pkgname-base=$pkgver-r$pkgrel + $pkgname-calc=$pkgver-r$pkgrel + $pkgname-common=$pkgver-r$pkgrel + $pkgname-draw=$pkgver-r$pkgrel + $pkgname-impress=$pkgver-r$pkgrel + $pkgname-math=$pkgver-r$pkgrel + $pkgname-connector-postgres=$pkgver-r$pkgrel + $pkgname-writer=$pkgver-r$pkgrel + " +# 1. Base dependencies +# 2. GUIs - gen +# 3. GUIs - gtk+2.0 +# 4. File formats +makedepends="apr-dev autoconf automake bash bison boost-dev cairo-dev + clucene-dev cmd:which coreutils cppunit-dev cups-dev dbus-glib-dev findutils + flex fontconfig-dev fontforge-dev freetype-dev glm gperf gpgme-dev + gst-plugins-base-dev gstreamer-dev harfbuzz-dev hunspell-dev hyphen-dev icu + icu-dev lcms2-dev libcmis-dev libexttextcat-dev libjpeg-turbo-dev + libnumbertext-dev libpng-dev libqrcodegen libxml2-utils libxslt-dev mdds~1.5 + mythes-dev neon-dev nss-dev openldap-dev openssl-dev perl poppler-dev + postgresql-dev python3-dev py3-lxml redland-dev sane-dev sed ucpp + unixodbc-dev util-linux xmlsec-dev zip + + libepoxy-dev libxinerama-dev libxrandr-dev libxrender-dev libxext-dev + + gtk+3.0-dev glib-dev mesa-dev + + libabw-dev libcdr-dev libe-book-dev libepubgen-dev libetonyek-dev + libfreehand-dev libmspub-dev libmwaw-dev libodfgen-dev liborcus-dev~0.15 + libpagemaker-dev libqxp-dev libstaroffice-dev libvisio-dev libwpd-dev + libwpg-dev libwps-dev libzmf-dev + " + +# -common also depends on these fonts +_fonts="ttf-liberation ttf-dejavu ttf-carlito" +checkdepends="$_fonts" + +# The order here is important. +# -doc comes first since it redirects manpages from the other subpackages +# -lang-* comes before -common since it redirects miscellaneous +# language-specific files from -common +subpackages="$pkgname-doc $pkgname-base $pkgname-gtk3 + $pkgname-calc $pkgname-draw $pkgname-impress $pkgname-math + $pkgname-connector-postgres $pkgname-writer" +source="https://download.documentfoundation.org/$pkgname/src/$_ver/$pkgname-$pkgver.tar.xz + https://download.documentfoundation.org/$pkgname/src/$_ver/$pkgname-dictionaries-$pkgver.tar.xz + https://download.documentfoundation.org/$pkgname/src/$_ver/$pkgname-translations-$pkgver.tar.xz + https://download.documentfoundation.org/$pkgname/src/$_ver/$pkgname-help-$pkgver.tar.xz + linux-musl.patch + fix-execinfo.patch + gettext-tiny.patch + disable-crc-test.patch + disable-outdated-font-test.patch + disable-mariadbc.patch + mso-lockfile-utf16le.patch + poppler-0.83.patch + " +ldpath="/usr/lib/$pkgname/program" + +_languages="af:Afrikaans:MPL-2.0 AND Public-Domain AND LGPL-3.0 AND LGPL-2.1+ AND Apache-2.0 + am:Amharic:MPL-2.0 AND Apache-2.0 + an:Aragonese:MPL-1.1 OR GPL-3.0+ OR LGPL-3.0+ + ar:Arabic:MPL-2.0 AND (GPL-2.0+ OR LGPL-2.1+ OR MPL-1.1+) AND Apache-2.0 + as:Assamese:MPL-2.0 AND Apache-2.0 + ast:Asturian:MPL-2.0 AND Apache-2.0 + be:Belarusian:MPL-2.0 AND CC-BY-SA-3.0 AND Apache-2.0 + bg:Bulgarian:MPL-2.0 AND GPL-2.0+ AND Apache-2.0 + bn:Bengali:MPL-2.0 AND GPL-2.0 AND Apache-2.0 + bn_in:Bengali (India):MPL-2.0 AND Apache-2.0 + bo:Tibetan:MPL-2.0 AND Apache-2.0 + br:Breton:MPL-2.0 AND LGPL-3.0 AND Apache-2.0 + brx:Bodo:MPL-2.0 AND Apache-2.0 + bs:Bosnian:MPL-2.0 AND Apache-2.0 + ca:Catalan:MPL-2.0 AND GPL-2.0+ AND GPL-3.0+ AND (GPL-3.0+ OR LGPL-3.0+) AND Apache-2.0 + ca_valencia:Catalan (Valencian):MPL-2.0 AND Apache-2.0 + cs:Czech:MPL-2.0 AND Custom AND Apache-2.0 + cy:Welsh (Cymraeg):MPL-2.0 AND Apache-2.0 + da:Danish:MPL-2.0 AND (GPL-2.0 OR LGPL-2.1 OR MPL-1.1) AND Apache-2.0 + de:German:MPL-2.0 AND (GPL-2.0 OR GPL-3.0 OR OASIS-0.1) AND Apache-2.0 + dgo:Dogri proper:MPL-2.0 AND Apache-2.0 + dz:Dzongkha:MPL-2.0 AND Apache-2.0 + el:Greek:MPL-2.0 AND (GPL-2.0 OR LGPL-2.1 OR MPL-1.1) AND Apache-2.0 + en_gb:English (UK):MPL-2.0 + en_us:English (US):MPL-2.0 AND Custom AND MIT AND (MPL-1.1 OR GPL-3.0+ OR LGPL-3.0+) AND GPL-2.0+ AND LGPL-2.1+ AND Apache-2.0 + en_za:English (South Africa):MPL-2.0 + eo:Esperanto:MPL-2.0 AND Apache-2.0 + es:Spanish:MPL-2.0 AND (GPL-3.0 OR LGPL-3.0 OR MPL-1.1) AND LGPL-2.1 AND Apache-2.0 + et:Estonian:MPL-2.0 AND LGPL-2.1 AND LPPL-1.3c AND Apache-2.0 + eu:Basque:MPL-2.0 AND Apache-2.0 + fa:Persian (Farsi):MPL-2.0 AND Apache-2.0 + fi:Finnish:MPL-2.0 AND Apache-2.0 + fr:French:MPL-2.0 AND (MPL-1.1+ OR GPL-2.0+ OR LGPL-2.1+) AND LPPL-1.3c AND LGPL-2.1+ AND Apache-2.0 + ga:Irish:MPL-2.0 AND Apache-2.0 + gd:Scottish Gaelic:MPL-2.0 AND GPL-3.0 AND Apache-2.0 + gl:Galician:MPL-2.0 AND GPL-3.0 AND Apache-2.0 + gu:Gujarati:MPL-2.0 AND GPL-3.0 AND Apache-2.0 + gug:Guaraní (Paraguay):MPL-2.0 AND Apache-2.0 + he:Hebrew:MPL-2.0 AND GPL-3.0 AND Apache-2.0 + hi:Hindi:MPL-2.0 AND GPL-2.0+ AND Apache-2.0 + hr:Croatian:MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + hu:Hungarian:MPL-2.0 AND (GPL-2.0+ OR LGPL-2.1+ OR MPL-1.1+) AND Apache-2.0 + id:Indonesian:MPL-2.0 AND Apache-2.0 + is:Icelandic:MPL-2.0 AND CC-BY-SA-3.0 AND Apache-2.0 + it:Italian:MPL-2.0 AND GPL-3.0 AND LGPL-3.0 AND Apache-2.0 + ja:Japanese:MPL-2.0 AND Apache-2.0 + ka:Georgian:MPL-2.0 AND Apache-2.0 + kk:Kazakh:MPL-2.0 AND Apache-2.0 + km:Khmer:MPL-2.0 AND Apache-2.0 + kmr_latn:Kurmanji Kurdish (Latin):MPL-2.0 AND Apache-2.0 + kn:Kannada:MPL-2.0 AND Apache-2.0 + ko:Korean:MPL-2.0 AND Apache-2.0 + kok:Konkani:MPL-2.0 AND Apache-2.0 + ks:Kashmiri:MPL-2.0 AND Apache-2.0 + lb:Luxembourgish:MPL-2.0 AND Apache-2.0 + lo:Lao:MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + lt:Lithuanian:MPL-2.0 AND BSD-3-Clause AND LPPL-1.3c AND Apache-2.0 + lv:Latvian:MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + mai:Maithili:MPL-2.0 AND Apache-2.0 + mk:Macedonian:MPL-2.0 AND Apache-2.0 + ml:Malayalam:MPL-2.0 AND Apache-2.0 + mn:Mongolian:MPL-2.0 AND Apache-2.0 + mni:Meithei (Manipuri):MPL-2.0 AND Apache-2.0 + mr:Marathi:MPL-2.0 AND Apache-2.0 + my:Burmese:MPL-2.0 AND Apache-2.0 + nb:Norwegian (Bokmal):MPL-2.0 AND Apache-2.0 + ne:Nepali:MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + nl:Dutch:MPL-2.0 AND (BSD-2-Clause OR CC-BY-3.0) AND Apache-2.0 + no:Norwegian:GPL-2.0 + nn:Nynorsk:MPL-2.0 AND Apache-2.0 + nr:Ndebele (South):MPL-2.0 AND Apache-2.0 + nso:Northern Sotho:MPL-2.0 AND Apache-2.0 + oc:Occitan:MPL-2.0 AND GPL-2.0+ AND Apache-2.0 + om:Oromo:MPL-2.0 AND Apache-2.0 + or:Oriya:MPL-2.0 AND Apache-2.0 + pa_in:Punjabi (India):MPL-2.0 AND Apache-2.0 + pl:Polish:MPL-2.0 AND (GPL OR LGPL OR MPL OR CC-SA-1.0) AND LGPL-3.0 AND LGPL-2.1 AND Apache-2.0 + pt:Portuguese:MPL-2.0 AND (GPL-2.0 OR LGPL-2.1 OR MPL-1.1) AND GPL-2.0 AND Apache-2.0 + pt_br:Portuguese (Brazil):MPL-2.0 AND (LGPL-3.0 OR MPL-1.1) AND (GPL-3.0+ OR LGPL-3.0+ OR MPL-1.1) AND Apache-2.0 + ro:Romanian:MPL-2.0 AND (GPL-2.0 OR LGPL-2.1 OR MPL-1.1) AND GPL-2.0 AND GPL-2.0+ AND Apache-2.0 + ru:Russian:MPL-2.0 AND (MPL-1.1 OR GPL OR LGPL) AND Custom AND LGPL AND Apache-2.0 + rw:Kinyarwanda:MPL-2.0 AND Apache-2.0 + sa_in:Sanskrit (India):MPL-2.0 AND Apache-2.0 + sat:Santali:MPL-2.0 AND Apache-2.0 + sd:Sindhi:MPL-2.0 AND Apache-2.0 + si:Sinhala:MPL-2.0 AND GPL-3.0 AND Apache-2.0 + sid:Sidamo:MPL-2.0 AND Apache-2.0 + sk:Slovak:MPL-2.0 AND (GPL-2.0 OR LGPL-2.1 OR MPL-1.1) AND LPPL-1.3c AND MIT AND Apache-2.0 + sl:Slovenian:MPL-2.0 AND (GPL-2.0 OR LGPL-2.1) AND LGPL-2.1 AND Apache-2.0 + sq:Albanian:MPL-2.0 AND Apache-2.0 + ss:Swati:MPL-2.0 AND Apache-2.0 + st:Southern Sotho:MPL-2.0 AND Apache-2.0 + sv:Swedish:MPL-2.0 AND LGPL-3.0 AND Custom AND Apache-2.0 + sw_tz:Swahili (Tanzania):MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + ta:Tamil:MPL-2.0 AND Apache-2.0 + te:Telugu:MPL-2.0 AND GPL-2.0+ AND (GPL-3.0+ OR LGPL-3.0+) AND Apache-2.0 + tg:Tajik:MPL-2.0 AND Apache-2.0 + th:Thai:MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + tn:Tswana:MPL-2.0 AND Apache-2.0 + tr:Turkish:MPL-2.0 AND Apache-2.0 + ts:Tsonga:MPL-2.0 AND Apache-2.0 + tt:Tatar:MPL-2.0 AND Apache-2.0 + ug:Uyghur:MPL-2.0 AND Apache-2.0 + uk:Ukrainian:MPL-2.0 AND (GPL-2.0+ OR LGPL-2.1+ OR MPL-1.1) AND GPL-2.0+ AND Apache-2.0 + uz:Uzbek:MPL-2.0 AND Apache-2.0 + ve:Venda:MPL-2.0 AND Apache-2.0 + vi:Vietnamese:MPL-2.0 AND GPL-2.0 AND Apache-2.0 + xh:Xhosa:MPL-2.0 AND Apache-2.0 + zh_cn:Simplified Chinese (People's Republic of China):MPL-2.0 AND Apache-2.0 + zh_tw:Traditional Chinese (Taiwan):MPL-2.0 AND Apache-2.0 + zu:Zulu:MPL-2.0 AND LGPL-2.1 AND Apache-2.0 + " +_lo_lang() { + local lang="$1" + case "$lang" in + # e.g. zh_cn -> zh_CN + *_[a-z][a-z]) lang="${lang%_*}_$(printf '%s' "${lang#*_}" | tr '[a-z]' '[A-Z]')";; + # e.g. sr_latn -> sr_Latn + *_latn) lang="${lang%_latn}_Latn";; + esac + printf '%s' "$lang" +} +_lo_languages="" +for _lang in $(printf '%s' "$_languages" | cut -d : -f 1); do + subpackages="$subpackages $pkgname-lang-$_lang:_split_lang:noarch" + # Seriously now. We even have secret languages that are not recognized + # by the configure script. These two languages only have dictionaries. + # c.f. _split_lang() + [ "$_lang" = "an" ] || [ "$_lang" = "no" ] && continue + + # --with-languages seems to prefer dashes instead of underscores + # when --with-myspell-dicts is given + _lang="$(_lo_lang "$_lang" | tr _ -)" + _lo_languages="$_lo_languages $_lang" +done +subpackages="$subpackages $pkgname-common" + +# secfixes: +# 6.4.0.3-r0: +# - CVE-2019-9848 +# - CVE-2019-9849 +# - CVE-2019-9850 +# - CVE-2019-9851 +# - CVE-2019-9852 +# - CVE-2019-9853 +# - CVE-2019-9854 + +prepare() { + default_prepare + NOCONFIGURE=1 ./autogen.sh +} + +build() { + export PYTHON="python3" + # Note: --with-parallelism must be specified since getconf does not + # recognize _NPROCESSORS_ONLN + + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --localstatedir=/var \ + --with-vendor="Adélie Linux" \ + --enable-symbols \ + --with-parallelism="$JOBS" \ + --disable-online-update \ + --disable-fetch-external \ + --disable-dependency-tracking \ + --enable-release-build \ + --enable-split-app-modules \ + --enable-python=system \ + --with-tls=nss \ + --with-system-libs \ + --with-system-ucpp \ + --with-help \ + --without-system-dicts \ + --with-external-tar="$srcdir" \ + --with-lang="$_lo_languages" \ + --with-myspell-dicts \ + --without-fonts \ + --disable-firebird-sdbc \ + --disable-coinmp \ + --disable-lpsolve \ + --enable-gtk3 \ + --disable-qt5 \ + --disable-odk \ + --disable-avahi \ + --disable-scripting-beanshell \ + --disable-scripting-javascript \ + --disable-sdremote \ + --disable-sdremote-bluetooth \ + --disable-pdfium \ + --disable-ooenv \ + --without-java \ + --disable-epm \ + --enable-build-opensymbol + + # adding '-isystem /usr/include' make things break with gcc6 + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823145 + sed -i -e 's:-isystem /usr/include[^/]::g' config_host.mk + + make build-nocheck +} + +check() { + make -k -j1 unitcheck +} + +package() { + make DESTDIR="$pkgdir" distro-pack-install +} + +doc() { + default_doc + pkgdesc="LibreOffice - man pages" + sed -i -e '\#^/usr/share/man#d' "$builddir"/file-lists/*.txt +} + +_split() { + local i + for i in $(grep -v ^%dir "$builddir/file-lists/${1}_list.txt" | sort -u); do + dirname="$(dirname $i)" + [ -d "$subpkgdir/$dirname" ] || install -dm755 "$subpkgdir/$dirname" + mv "$pkgdir/$i" "$subpkgdir/$i" + done +} + +_move_from() { + orig_pkg="$1" # original owner of $path + path="$2" # file/directory to move + dest="$3" # destination directory, automatically under $subpkgdir + + sed -i -e "\\#^\\(%dir \\)*/${path#$pkgdir/}#d" \ + "$builddir/file-lists/${orig_pkg}_list.txt" + [ -d "$subpkgdir/$dest" ] || install -dm755 "$subpkgdir/$dest" + mv "$path" "$subpkgdir/$dest" +} + +_split_lang() { + local i lang entry dict dictdir auto autodir wiz wizdir logo logodir + lang="${subpkgname#$pkgname-lang-}" + entry="$(printf '%s' "$_languages" | grep "^\\s*$lang")" + lang="$(_lo_lang "$lang")" + + pkgdesc="LibreOffice - $(printf '%s' "$entry" | cut -d : -f 2) language pack" + license="$(printf '%s' "$entry" | cut -d : -f 3)" + depends="" + + # Includes translations/messages and help packs initially + _split "lang_$lang" + # Everything else we must move by hand + + dictdir="usr/lib/libreoffice/share/extensions" + case "$lang" in + # en_US is installed by default, so it will own most of the English files + en_US) dict="en";; + pt) dict="pt-PT";; + *) dict="$(printf '%s' "$lang" | tr _ -)";; + esac + if [ -d "$pkgdir/$dictdir/dict-$dict" ]; then + _move_from common "$pkgdir/$dictdir/dict-$dict" "$dictdir" + fi + # Again, these languages only have dictionaries + [ "$_lang" = "an" ] || [ "$_lang" = "no" ] && return 0 + + autodir="usr/lib/libreoffice/share/autocorr" + case "$lang" in + de) auto="de";; + en_US) auto="en-[A-Z][A-Z]";; + en_*) auto="skip";; + es) auto="es";; + fr) auto="fr";; + it) auto="it";; + pt) auto="pt-PT";; + pt_BR) auto="pt-BR";; + *_[A-Z][A-Z]) auto="$(printf '%s' "$lang" | tr _ -)";; + *_Latn) auto="${lang%_Latn}-Latn-[A-Z][A-Z]";; + *) auto="$lang-[A-Z][A-Z]";; + esac + for i in $(find "$pkgdir/$autodir" -name "acor_$auto.dat"); do + _move_from common "$i" "$autodir" + done + + wizdir="usr/lib/libreoffice/share/wizards" + case "$lang" in + en_US) wiz="en_[A-Z][A-Z]";; + en_*) wiz="skip";; + *) wiz="$lang";; + esac + for i in $(find "$pkgdir/$wizdir" -name "resources_$wiz.properties"); do + _move_from common "$i" "$wizdir" + done + + logodir="usr/lib/libreoffice/share/Scripts/python/LibreLogo" + case "$lang" in + en_US) logo="en_[A-Z][A-Z]";; + en_*) logo="skip";; + *) logo="$lang";; + esac + for i in $(find "$pkgdir/$logodir" -name "LibreLogo_$logo.properties"); do + _move_from common "$i" "$logodir" + done +} + +common() { + pkgdesc="LibreOffice - common files" + depends="$pkgname-lang-en_us=$pkgver-r$pkgrel $_fonts !$pkgname-gtk2" + + _split common + + mkdir -p "$subpkgdir/usr/share/appdata" + mv "$pkgdir"/usr/share/appdata/*.xml "$subpkgdir/usr/share/appdata" + + mkdir -p "$subpkgdir"/usr/lib/libreoffice/share + mv "$pkgdir"/usr/lib/libreoffice/share/libreofficekit \ + "$subpkgdir"/usr/lib/libreoffice/share/libreofficekit + + # At this point there should only be empty directories left in + # the "libreoffice" metapackage + if [ -n "$(find "$pkgdir" -type f)" ]; then + error "Files still in 'libreoffice' package:" + find "$pkgdir" -type f | sed "s#^$pkgdir/#\\t#" + return 1 + fi +} + +gtk3() { + pkgdesc="LibreOffice - GTK+3.0 GUI" + depends="libreoffice-common=$pkgver-r$pkgrel" + install_if="$pkgname-common=$pkgver-r$pkgrel gtk+3.0" + _split gnome +} + +base() { + pkgdesc="LibreOffice - database frontend" + depends="libreoffice-common=$pkgver-r$pkgrel" + _split base +} + +calc() { + pkgdesc="LibreOffice - spreadsheet editor" + depends="libreoffice-common=$pkgver-r$pkgrel" + _split calc +} + +draw() { + pkgdesc="LibreOffice - drawing application" + depends="libreoffice-common=$pkgver-r$pkgrel" + _split draw +} + +impress() { + pkgdesc="LibreOffice - presentation application" + depends="libreoffice-common=$pkgver-r$pkgrel" + _split impress +} + +math() { + pkgdesc="LibreOffice - equation editor" + depends="libreoffice-common=$pkgver-r$pkgrel" + _split math +} + +postgres() { + pkgdesc="LibreOffice - connector for PostgreSQL database" + depends="libreoffice-base=$pkgver-r$pkgrel" + _split postgresql +} + +writer() { + pkgdesc="LibreOffice - word processor" + depends="libreoffice-common=$pkgver-r$pkgrel" + _split writer +} + +sha512sums="1ea4b5865b7ad7d7400a775e153b00aa01d188844b580b26adb0d513db5f29a880cac145a746f139d236fff8fb5e8ed316943551de2e2eea218ab96bf177ca42 libreoffice-6.4.0.3.tar.xz +6e6bd33c86b6fe0744b9db70982aca8032011ceda55db30a8214b822dd77ad4760518f58aa42fed10996081ce91bf791fc332a8273664d5dd2141cc88eaaba97 libreoffice-dictionaries-6.4.0.3.tar.xz +168800ec5526f69febf6f37df4d04c0c42d26595587339721141c40c9812d9398bef7618732244759d65b4ccf46072b65536504c37c95f73e1ab91e6582ee75d libreoffice-translations-6.4.0.3.tar.xz +f3f0b5e9f09e55c49a74439e4355dfebc3fe0b6ec809eee44d58fa8493454828ea6af9aab6f336c74394aab0a71fa7d0aa3485d4f662f9917bfb798ad3164e13 libreoffice-help-6.4.0.3.tar.xz +91e3659232a6427234d483289892e1c66673ad2abef792cec9bf905f35797893faba59f10d775cdd0bad23d2be7b77578747dfa707d55bef62a2fbdc95ba3d2c linux-musl.patch +ed18d6bc6e03369e17b50e6b969ac0804984c1416fdfe7120251d11c59a791bb0fc8956f848ee8697fce3c074f2943b03d4441aa531ff9504be2f497a8e7e412 fix-execinfo.patch +bac06a1f0f6ef3e5860ec340470583b2a7ff079efa9efee9119ae1ac320b97ecbfdb7eba63975d4f7a4e2476d3b01a9508a53a84b49df0a8febe12e17b685529 gettext-tiny.patch +ebfc1276a14354bb6b7274bd7850b7fe2b1653c379b1e04023c9fce65eaace4214b2e79d302a075b848297f454b3d340cf5e7db3565a69a2dfaecd4c98d6e669 disable-crc-test.patch +4ffc389a3c545d37d152bb52390c3abd06a32eb9fee03110c07e8b57f9b9d1be68fdc5092ad0be76f6540367a1f1d2e9e32d519021d8205847594edb811da428 disable-outdated-font-test.patch +a4b63e741cd0aa295440a79142f221f2526ae7ba4f2fd28f37366871970c539332de70d89dfe8682d917aa70131b7c3a703e592e88085b58d024659105f8066a disable-mariadbc.patch +52f2e36b77fd952293d5bcd75d58aaee52faa846764d39c9f066778dfb7c7dcd3a6ab7ff6aeb8bd4a5671cec450888638f7c628c0302c7603e07b582c84ca556 mso-lockfile-utf16le.patch +38b09913075219e6d9bc34e94f995653941909118e96f89f7cf45798682758c541ff182b6643e45c7f20dfbb1c4c03e51ea4d8cdd15a997718f297c3c78245b5 poppler-0.83.patch" diff --git a/legacy/libreoffice/disable-crc-test.patch b/legacy/libreoffice/disable-crc-test.patch new file mode 100644 index 000000000..474408514 --- /dev/null +++ b/legacy/libreoffice/disable-crc-test.patch @@ -0,0 +1,62 @@ +--- libreoffice-6.3.1.2/vcl/qa/cppunit/svm/svmtest.cxx 2019-08-29 16:51:57.000000000 -0500 ++++ libreoffice-6.3.1.2/vcl/qa/cppunit/svm/svmtest.cxx 2019-09-12 20:46:12.114022513 -0500 +@@ -896,14 +896,13 @@ void SvmTest::checkBitmaps(const GDIMeta + } + #endif + +- assertXPathAttrs(pDoc, "/metafile/bmp[1]", {{"x", "1"}, {"y", "2"}, {"crc", crc1}}); ++ assertXPathAttrs(pDoc, "/metafile/bmp[1]", {{"x", "1"}, {"y", "2"}}); + assertXPathAttrs(pDoc, "/metafile/bmpscale[1]", { +- {"x", "1"}, {"y", "2"}, {"width", "3"}, {"height", "4"}, {"crc", crc2} ++ {"x", "1"}, {"y", "2"}, {"width", "3"}, {"height", "4"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpscalepart[1]", { + {"destx", "1"}, {"desty", "2"}, {"destwidth", "3"}, {"destheight", "4"}, +- {"srcx", "2"}, {"srcy", "1"}, {"srcwidth", "4"}, {"srcheight", "3"}, +- {"crc", crc3} ++ {"srcx", "2"}, {"srcy", "1"}, {"srcwidth", "4"}, {"srcheight", "3"} + }); + } + +@@ -973,33 +972,33 @@ void SvmTest::checkBitmapExs(const GDIMe + } + + assertXPathAttrs(pDoc, "/metafile/bmpex[1]", { +- {"x", "1"}, {"y", "1"}, {"crc", aExpectedCRC[0]}, {"transparenttype", "bitmap"} ++ {"x", "1"}, {"y", "1"}, {"transparenttype", "bitmap"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpexscale[1]", { + {"x", "5"}, {"y", "0"}, {"width", "2"}, {"height", "3"}, +- {"crc", aExpectedCRC[1]}, {"transparenttype", "bitmap"} ++ {"transparenttype", "bitmap"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpexscalepart[1]", { + {"destx", "7"}, {"desty", "1"}, {"destwidth", "2"}, {"destheight", "2"}, + {"srcx", "0"}, {"srcy", "0"}, {"srcwidth", "3"}, {"srcheight", "4"}, +- {"crc", aExpectedCRC[2]}, {"transparenttype", "bitmap"} ++ {"transparenttype", "bitmap"} + }); + + #ifndef MACOSX + assertXPathAttrs(pDoc, "/metafile/bmpex[2]", { +- {"x", "6"}, {"y", "6"}, {"crc", aExpectedCRC[3]}, {"transparenttype", "bitmap"} ++ {"x", "6"}, {"y", "6"}, {"transparenttype", "bitmap"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpex[3]", { +- {"x", "0"}, {"y", "6"}, {"crc", aExpectedCRC[4]}, {"transparenttype", "bitmap"} ++ {"x", "0"}, {"y", "6"}, {"transparenttype", "bitmap"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpex[4]", { +- {"x", "2"}, {"y", "6"}, {"crc", aExpectedCRC[5]}, {"transparenttype", "bitmap"} ++ {"x", "2"}, {"y", "6"}, {"transparenttype", "bitmap"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpex[5]", { +- {"x", "0"}, {"y", "8"}, {"crc", aExpectedCRC[6]}, {"transparenttype", "bitmap"} ++ {"x", "0"}, {"y", "8"}, {"transparenttype", "bitmap"} + }); + assertXPathAttrs(pDoc, "/metafile/bmpex[6]", { +- {"x", "2"}, {"y", "8"}, {"crc", aExpectedCRC[7]}, {"transparenttype", "bitmap"} ++ {"x", "2"}, {"y", "8"}, {"transparenttype", "bitmap"} + }); + #endif + } diff --git a/legacy/libreoffice/disable-mariadbc.patch b/legacy/libreoffice/disable-mariadbc.patch new file mode 100644 index 000000000..f63692775 --- /dev/null +++ b/legacy/libreoffice/disable-mariadbc.patch @@ -0,0 +1,13 @@ +We don't have MariaDB yet and there is no ./configure option for it + +--- libreoffice-6.2.3.2/configure.ac ++++ libreoffice-6.2.3.2/configure.ac +@@ -8471,7 +8471,7 @@ + AC_SUBST(PYTHON_VERSION_MAJOR) + AC_SUBST(PYTHON_VERSION_MINOR) + +-ENABLE_MARIADBC=TRUE ++ENABLE_MARIADBC= + if test "$_os" = "Android" -o "$_os" = "iOS" -o "$enable_mpl_subset" = "yes"; then + ENABLE_MARIADBC= + fi diff --git a/legacy/libreoffice/disable-outdated-font-test.patch b/legacy/libreoffice/disable-outdated-font-test.patch new file mode 100644 index 000000000..02470d69a --- /dev/null +++ b/legacy/libreoffice/disable-outdated-font-test.patch @@ -0,0 +1,16 @@ +https://www.mail-archive.com/libreoffice@lists.freedesktop.org/msg217102.html + +--- libreoffice-6.2.1.2/editeng/qa/unit/core-test.cxx 2019-02-26 10:41:25.000000000 -0500 ++++ libreoffice-6.2.1.2/editeng/qa/unit/core-test.cxx 2019-03-11 04:28:15.930763760 -0400 +@@ -198,11 +198,6 @@ void Test::testLineSpacing() + const SvxLineSpacingItem& rLSItem = pNode->GetContentAttribs().GetItem(EE_PARA_SBL); + CPPUNIT_ASSERT_EQUAL(SvxInterLineSpaceRule::Prop, rLSItem.GetInterLineSpaceRule()); + CPPUNIT_ASSERT_EQUAL(nSpace, rLSItem.GetPropLineSpace()); +- +- // Check the first line +- ParagraphInfos aInfo = aEditEngine.GetParagraphInfos(0); +- CPPUNIT_ASSERT_EQUAL(nExpMaxAscent, aInfo.nFirstLineMaxAscent); +- CPPUNIT_ASSERT_EQUAL(nExpLineHeight, aEditEngine.GetLineHeight(0)); + }; + + // Test first case - 60% diff --git a/legacy/libreoffice/fix-execinfo.patch b/legacy/libreoffice/fix-execinfo.patch new file mode 100644 index 000000000..cb82b7d84 --- /dev/null +++ b/legacy/libreoffice/fix-execinfo.patch @@ -0,0 +1,33 @@ +--- libreoffice-6.2.1.2/sal/osl/unx/backtrace.h ++++ libreoffice-6.2.1.2/sal/osl/unx/backtrace.h +@@ -20,7 +20,7 @@ + #ifndef INCLUDED_SAL_OSL_UNX_BACKTRACE_H + #define INCLUDED_SAL_OSL_UNX_BACKTRACE_H + +-#if defined (LINUX) ++#if defined (LINUX) && defined (__GLIBC__) + + #include <execinfo.h> + +--- libreoffice-6.2.1.2/sal/osl/unx/signal.cxx ++++ libreoffice-6.2.1.2/sal/osl/unx/signal.cxx +@@ -35,7 +35,7 @@ + + #endif /* MACOSX */ + +-#ifdef LINUX ++#if defined(LINUX) && defined(__GLIBC__) + #include <execinfo.h> + #include <link.h> + #define INCLUDE_BACKTRACE +--- libreoffice-6.2.1.2/sal/osl/unx/backtrace.c ++++ libreoffice-6.2.1.2/sal/osl/unx/backtrace.c +@@ -279,7 +279,7 @@ void backtrace_symbols_fd( void **buffer + } + } + +-#elif !defined LINUX ++#elif !defined(__GLIBC__) + + int backtrace( void **buffer, int max_frames ) + { diff --git a/legacy/libreoffice/gettext-tiny.patch b/legacy/libreoffice/gettext-tiny.patch new file mode 100644 index 000000000..a63f45553 --- /dev/null +++ b/legacy/libreoffice/gettext-tiny.patch @@ -0,0 +1,38 @@ +gettext-tiny does not currently ship msguniq, so let's cheat around it + +--- libreoffice-6.2.1.2/solenv/gbuild/AllLangMoTarget.mk ++++ libreoffice-6.2.1.2/solenv/gbuild/AllLangMoTarget.mk +@@ -40,10 +40,10 @@ + $(call gb_Helper_abbreviate_dirs,\ + mkdir -p $(dir $@) && \ + if test -e $(gb_POLOCATION)/$(LANGUAGE)/$(POLOCATION)/messages.po; then \ +- $(MSGUNIQ) --force-po $(gb_POLOCATION)/$(LANGUAGE)/$(POLOCATION)/messages.po | $(MSGFMT) - -o $@; \ ++ cat $(gb_POLOCATION)/$(LANGUAGE)/$(POLOCATION)/messages.po | $(MSGFMT) - -o $@; \ + else \ + echo missing $(gb_POLOCATION)/$(LANGUAGE)/$(POLOCATION)/messages.po && \ +- $(MSGUNIQ) --force-po $(SRCDIR)/solenv/bin/dummy.po | $(MSGFMT) - -o $@; \ ++ cat $(SRCDIR)/solenv/bin/dummy.po | $(MSGFMT) - -o $@; \ + fi) + + #$(info $(call gb_MoTarget_get_target,$(1))) +--- libreoffice-6.2.1.2/configure.ac ++++ libreoffice-6.2.1.2/configure.ac +@@ -12106,18 +12106,6 @@ else + fi + fi + fi +- if test -z "$MSGUNIQ"; then +- if test -n "$LODE_HOME" -a -x "$LODE_HOME/opt/bin/msguniq" ; then +- MSGUNIQ="$LODE_HOME/opt/bin/msguniq" +- elif test -x "/opt/lo/bin/msguniq"; then +- MSGUNIQ="/opt/lo/bin/msguniq" +- else +- AC_CHECK_PROGS(MSGUNIQ, [msguniq]) +- if test -z "$MSGUNIQ"; then +- AC_MSG_ERROR([msguniq not found. Install GNU gettext, or re-run without languages.]) +- fi +- fi +- fi + fi + AC_SUBST(MSGFMT) + AC_SUBST(MSGUNIQ) diff --git a/legacy/libreoffice/linux-musl.patch b/legacy/libreoffice/linux-musl.patch new file mode 100644 index 000000000..2641620cb --- /dev/null +++ b/legacy/libreoffice/linux-musl.patch @@ -0,0 +1,42 @@ +--- libreoffice-6.4.0.3/configure.ac 2020-01-22 23:14:16.000000000 +0000 ++++ libreoffice-6.4.0.3/configure.ac 2020-02-04 04:09:34.970114523 +0000 +@@ -612,7 +612,7 @@ solaris*) + fi + ;; + +-linux-gnu*|k*bsd*-gnu*) ++linux-gnu*|linux-musl*|k*bsd*-gnu*) + build_gstreamer_1_0=yes + test_kf5=yes + test_gtk3_kde5=yes +@@ -4341,7 +4341,7 @@ kfreebsd*) + esac + ;; + +-linux-gnu*) ++linux-gnu*|linux-musl*) + COM=GCC + USING_X11=TRUE + OS=LINUX +@@ -10232,21 +10232,6 @@ AC_SUBST(SYSTEM_LIBNUMBERTEXT_DATA) + AC_SUBST(ENABLE_LIBNUMBERTEXT) + AC_SUBST(LIBNUMBERTEXT_CFLAGS) + +-dnl *************************************** +-dnl testing libc version for Linux... +-dnl *************************************** +-if test "$_os" = "Linux"; then +- AC_MSG_CHECKING([whether libc is >= 2.1.1]) +- exec 6>/dev/null # no output +- AC_CHECK_LIB(c, gnu_get_libc_version, HAVE_LIBC=yes; export HAVE_LIBC) +- exec 6>&1 # output on again +- if test "$HAVE_LIBC"; then +- AC_MSG_RESULT([yes]) +- else +- AC_MSG_ERROR([no, upgrade libc]) +- fi +-fi +- + dnl ========================================= + dnl Check for uuidgen + dnl ========================================= diff --git a/legacy/libreoffice/mso-lockfile-utf16le.patch b/legacy/libreoffice/mso-lockfile-utf16le.patch new file mode 100644 index 000000000..e71413e0a --- /dev/null +++ b/legacy/libreoffice/mso-lockfile-utf16le.patch @@ -0,0 +1,33 @@ +--- libreoffice-6.3.1.2/svl/source/misc/msodocumentlockfile.cxx 2019-08-29 16:51:57.000000000 -0500 ++++ libreoffice-6.3.1.2/svl/source/misc/msodocumentlockfile.cxx 2019-09-15 04:19:32.593900468 -0500 +@@ -12,6 +12,7 @@ + #include <algorithm> + #include <ucbhelper/content.hxx> + #include <comphelper/processfactory.hxx> ++#include <oox/helper/helper.hxx> + + #include <com/sun/star/io/IOException.hpp> + #include <com/sun/star/io/XOutputStream.hpp> +@@ -220,7 +221,7 @@ LockFileEntry MSODocumentLockFile::GetLo + const int nACPLen = aBuf[0]; + if (nACPLen > 0 && nACPLen <= 52) // skip wrong format + { +- const sal_Int8* pBuf = aBuf.getConstArray() + 54; ++ sal_Int8* pBuf = aBuf.getArray() + 54; + int nUTF16Len = *pBuf; // try Word position + // If UTF-16 length is 0x20, then ACP length is also less than maximal, which means + // that in Word lockfile case, at least two preceding bytes would be zero. Both +@@ -228,9 +229,12 @@ LockFileEntry MSODocumentLockFile::GetLo + if (nUTF16Len == 0x20 && (*(pBuf - 1) != 0 || *(pBuf - 2) != 0)) + nUTF16Len = *++pBuf; // use Excel/PowerPoint position + +- if (nUTF16Len > 0 && nUTF16Len <= 52) // skip wrong format ++ if (nUTF16Len > 0 && nUTF16Len <= 52) { // skip wrong format ++ oox::ByteOrderConverter::convertLittleEndianArray( ++ reinterpret_cast<sal_Unicode*>(pBuf + 2), nUTF16Len); + aResult[LockFileComponent::OOOUSERNAME] + = OUString(reinterpret_cast<const sal_Unicode*>(pBuf + 2), nUTF16Len); ++ } + } + } + return aResult; diff --git a/legacy/libreoffice/poppler-0.83.patch b/legacy/libreoffice/poppler-0.83.patch new file mode 100644 index 000000000..57cf13c52 --- /dev/null +++ b/legacy/libreoffice/poppler-0.83.patch @@ -0,0 +1,70 @@ +From 9065cd8d9a19864f6b618f2dc10daf577badd9ee Mon Sep 17 00:00:00 2001 +From: Martin Milata <martin@martinmilata.cz> +Date: Wed, 4 Dec 2019 02:37:40 +0100 +Subject: [PATCH] Fix build with poppler-0.83 + +Change-Id: I7a3684932b8f9c403a3368b42fa4d8039c67f1a9 +Reviewed-on: https://gerrit.libreoffice.org/84384 +Tested-by: Jenkins +Reviewed-by: Michael Stahl <michael.stahl@cib.de> +--- + sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx | 7 +++++++ + sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.hxx | 4 ++++ + sdext/source/pdfimport/xpdfwrapper/wrapper_gpl.cxx | 4 ++++ + 3 files changed, 15 insertions(+) + +diff --git a/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx b/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx +index 26048177e87d..e9c2a407c279 100644 +--- a/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx ++++ b/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.cxx +@@ -491,11 +491,18 @@ void PDFOutDev::writeFontFile( GfxFont* gfxFont ) const + gfree(pBuf); + } + ++#if POPPLER_CHECK_VERSION(0, 83, 0) ++void PDFOutDev::printPath( const GfxPath* pPath ) ++#else + void PDFOutDev::printPath( GfxPath* pPath ) ++#endif + { + int nSubPaths = pPath ? pPath->getNumSubpaths() : 0; + for( int i=0; i<nSubPaths; i++ ) + { ++#if POPPLER_CHECK_VERSION(0, 83, 0) ++ const ++#endif + GfxSubpath* pSub = pPath->getSubpath( i ); + const int nPoints = pSub->getNumPoints(); + +diff --git a/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.hxx b/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.hxx +index 02f6b59f6f15..2e7d2186f9a1 100644 +--- a/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.hxx ++++ b/sdext/source/pdfimport/xpdfwrapper/pdfioutdev_gpl.hxx +@@ -149,7 +149,11 @@ namespace pdfi + + int parseFont( long long nNewId, GfxFont* pFont, GfxState* state ) const; + void writeFontFile( GfxFont* gfxFont ) const; ++#if POPPLER_CHECK_VERSION(0, 83, 0) ++ static void printPath( const GfxPath* pPath ); ++#else + static void printPath( GfxPath* pPath ); ++#endif + + public: + explicit PDFOutDev( PDFDoc* pDoc ); +diff --git a/sdext/source/pdfimport/xpdfwrapper/wrapper_gpl.cxx b/sdext/source/pdfimport/xpdfwrapper/wrapper_gpl.cxx +index 42178b650cdd..b1a54bd09c5f 100644 +--- a/sdext/source/pdfimport/xpdfwrapper/wrapper_gpl.cxx ++++ b/sdext/source/pdfimport/xpdfwrapper/wrapper_gpl.cxx +@@ -68,7 +68,11 @@ int main(int argc, char **argv) + } + + // read config file ++#if POPPLER_CHECK_VERSION(0, 83, 0) ++ globalParams = std::make_unique<GlobalParams>(); ++#else + globalParams = new GlobalParams(); ++#endif + globalParams->setErrQuiet(true); + #if defined(_MSC_VER) + globalParams->setupBaseFonts(nullptr); diff --git a/legacy/libvpx/libm-pc.patch b/legacy/libvpx/libm-pc.patch deleted file mode 100644 index 87f07a398..000000000 --- a/legacy/libvpx/libm-pc.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- ./libs.mk.orig -+++ ./libs.mk -@@ -241,7 +241,7 @@ - $(qexec)echo 'Version: $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)' >> $@ - $(qexec)echo 'Requires:' >> $@ - $(qexec)echo 'Conflicts:' >> $@ -- $(qexec)echo 'Libs: -L$${libdir} -lvpx' >> $@ -+ $(qexec)echo 'Libs: -L$${libdir} -lvpx -lm' >> $@ - $(qexec)echo 'Cflags: -I$${includedir}' >> $@ - INSTALL-LIBS-yes += $(LIBSUBDIR)/pkgconfig/vpx.pc - INSTALL_MAPS += $(LIBSUBDIR)/pkgconfig/%.pc %.pc diff --git a/legacy/llvm8/APKBUILD b/legacy/llvm8/APKBUILD new file mode 100644 index 000000000..a7a2a44d3 --- /dev/null +++ b/legacy/llvm8/APKBUILD @@ -0,0 +1,241 @@ +# Contributor: Travis Tilley <ttilley@gmail.com> +# Contributor: Mitch Tishmack <mitch.tishmack@gmail.com> +# Contributor: Jakub Jirutka <jakub@jirutka.cz> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +_pkgname=llvm +pkgver=8.0.1 +_majorver=${pkgver%%.*} +pkgname=$_pkgname$_majorver +pkgrel=3 +pkgdesc="Low Level Virtual Machine compiler system, version $_majorver" +arch="all" +options="!checkroot !dbg" +url="https://llvm.org/" +license="NCSA" +depends_dev="$pkgname=$pkgver-r$pkgrel libexecinfo-dev libxml2-dev" +makedepends="binutils-dev chrpath cmake file libexecinfo-dev libffi-dev + libxml2-dev python3 zlib-dev" +subpackages="$pkgname-static $pkgname-libs $pkgname-dev + $pkgname-test-utils:_test_utils" +source="https://github.com/llvm/llvm-project/releases/download/llvmorg-$pkgver/llvm-$pkgver.src.tar.xz + llvm-fix-build-with-musl-libc.patch + disable-FileSystemTest.CreateDir-perms-assert.patch + disable-dlclose-test.patch + musl-ppc64-elfv2.patch + more-secure-plt.patch + even-more-secure-plt.patch + python3-test.patch + scc-insertion.patch + fix-memory-mf_exec-on-aarch64.patch + " +builddir="$srcdir/$_pkgname-$pkgver.src" + +# ARM has few failures in test suite that we don't care about currently and +# also it takes forever to run them on the builder. +case "$CARCH" in + arm*) options="$options !check";; +esac + +# Whether is this package the default (latest) LLVM version. +_default_llvm="no" + +if [ "$_default_llvm" = yes ]; then + provides="llvm=$pkgver-r$pkgrel" + replaces="llvm" +fi + +# NOTE: It seems that there's no (sane) way how to change includedir, sharedir +# etc. separately, just the CMAKE_INSTALL_PREFIX. Standard CMake variables and +# even LLVM-specific variables, that are related to these paths, actually +# don't work (in llvm 3.7). +# +# When building a software that depends on LLVM, utility llvm-config should be +# used to discover where is LLVM installed. It provides options to print +# path of bindir, includedir, and libdir separately, but in its source, all +# these paths are actually hard-coded against INSTALL_PREFIX. We can patch it +# and move paths manually, but I'm really not sure what it may break... +# +# Also note that we should *not* add version suffix to files in llvm bindir! +# It breaks build system of some software that depends on LLVM, because they +# don't expect these files to have a sufix. +# +# So, we install all the LLVM files into /usr/lib/llvm$_majorver. +# BTW, Fedora and Debian do the same thing. +# +_prefix="usr/lib/llvm$_majorver" + +prepare() { + default_prepare + + # https://bugs.llvm.org//show_bug.cgi?id=31870 + rm test/tools/llvm-symbolizer/print_context.c +} + +build() { + # Auto-detect it by guessing either. + local ffi_include_dir="$(pkg-config --cflags-only-I libffi | sed 's|^-I||g')" + + cmake -G "Unix Makefiles" -Wno-dev \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/$_prefix \ + -DCMAKE_VERBOSE_MAKEFILE=NO \ + -DFFI_INCLUDE_DIR="$ffi_include_dir" \ + -DLLVM_BINUTILS_INCDIR=/usr/include \ + -DLLVM_BUILD_DOCS=OFF \ + -DLLVM_BUILD_EXAMPLES=OFF \ + -DLLVM_BUILD_EXTERNAL_COMPILER_RT=ON \ + -DLLVM_BUILD_LLVM_DYLIB=ON \ + -DLLVM_BUILD_TESTS=ON \ + -DLLVM_DEFAULT_TARGET_TRIPLE="$CBUILD" \ + -DLLVM_ENABLE_ASSERTIONS=OFF \ + -DLLVM_ENABLE_CXX1Y=ON \ + -DLLVM_ENABLE_FFI=ON \ + -DLLVM_ENABLE_LIBCXX=OFF \ + -DLLVM_ENABLE_PIC=ON \ + -DLLVM_ENABLE_RTTI=ON \ + -DLLVM_ENABLE_SPHINX=OFF \ + -DLLVM_ENABLE_TERMINFO=ON \ + -DLLVM_ENABLE_ZLIB=ON \ + -DLLVM_HOST_TRIPLE="$CHOST" \ + -DLLVM_INCLUDE_EXAMPLES=OFF \ + -DLLVM_LINK_LLVM_DYLIB=ON \ + -DLLVM_TARGETS_TO_BUILD='AArch64;AMDGPU;ARM;BPF;Hexagon;Lanai;Mips;MSP430;PowerPC;Sparc;SystemZ;WebAssembly;X86;XCore' \ + -DPYTHON_EXECUTABLE=/usr/bin/python3 \ + -Bbuild . + + make -C build llvm-tblgen + make -C build + + python3 utils/lit/setup.py build +} + +check() { + # appears to be an issue on musl and glibc, but only fails on musl: + # https://github.com/NixOS/nixpkgs/blob/bb7e9e46/pkgs/development/compilers/llvm/8/llvm.nix#L74 + rm -f "$builddir"/test/CodeGen/AArch64/wineh4.mir + make -C build check-llvm +} + +package() { + make DESTDIR="$pkgdir" -C build install + + cd "$pkgdir"/$_prefix + + # Remove RPATHs. + file lib/*.so bin/* \ + | awk -F: '$2~/ELF/{print $1}' \ + | xargs -r chrpath -d + + # Symlink files from /usr/lib/llvm*/bin to /usr/bin. + mkdir -p "$pkgdir"/usr/bin + local name newname path + for path in bin/*; do + name=${path##*/} + # Add version infix/suffix to the executable name. + case "$name" in + llvm-*) newname="llvm$_majorver-${name#llvm-}";; + *) newname="$name$_majorver";; + esac + # If this package provides=llvm (i.e. it's the default/latest + # llvm package), omit version infix/suffix. + if [ "$_default_llvm" = yes ]; then + newname=$name + fi + case "$name" in + FileCheck | obj2yaml | yaml2obj) continue;; + esac + ln -s ../lib/llvm$_majorver/bin/$name "$pkgdir"/usr/bin/$newname + done + + # Move /usr/lib/$pkgname/include/ into /usr/include/$pkgname/ + # and symlink it back. + _mv include/* "$pkgdir"/usr/include/$pkgname/ + rmdir include + ln -s ../../include/$pkgname include + + ln -s "$pkgdir"/usr/lib/cmake/llvm ../$pkgname/lib/cmake/llvm +} + +static() { + pkgdesc="LLVM $_majorver static libraries" + _common_subpkg + + _mv "$pkgdir"/$_prefix/lib/*.a "$subpkgdir"/$_prefix/lib/ + strip -d "$subpkgdir"/$_prefix/lib/*.a +} + +libs() { + pkgdesc="LLVM $_majorver runtime library" + local soname="libLLVM-$_majorver.so" + local soname2="libLLVM-$pkgver.so" + _common_subpkg + + mkdir -p "$subpkgdir" + cd "$subpkgdir" + + # libLLVM should be in /usr/lib. This is needed for binaries that are + # dynamically linked with libLLVM, so they can find it on default path. + _mv "$pkgdir"/$_prefix/lib/$soname usr/lib/ + ln -s $soname usr/lib/$soname2 + + # And also symlink it back to the LLVM prefix. + mkdir -p $_prefix/lib + ln -s ../../$soname $_prefix/lib/$soname + ln -s ../../$soname $_prefix/lib/$soname2 +} + +dev() { + _common_subpkg + default_dev + cd "$subpkgdir" + + _mv "$pkgdir"/$_prefix/lib $_prefix/ + _mv "$pkgdir"/$_prefix/include $_prefix/ + + _mv "$pkgdir"/$_prefix/bin/llvm-config $_prefix/bin/ +} + +_test_utils() { + pkgdesc="LLVM $_majorver utilities for executing LLVM and Clang style test suites" + depends="python3" + _common_subpkg + replaces="" + + local litver="$(python3 "$builddir"/utils/lit/setup.py --version 2>/dev/null \ + | sed 's/\.dev.*$//')" + test -n "$litver" || return 1 + provides="$provides lit=$litver-r$pkgrel" + + cd "$builddir"/build + + install -D -m 755 bin/FileCheck "$subpkgdir"/$_prefix/bin/FileCheck + install -D -m 755 bin/count "$subpkgdir"/$_prefix/bin/count + install -D -m 755 bin/not "$subpkgdir"/$_prefix/bin/not + + python3 ../utils/lit/setup.py install --prefix=/usr --root="$subpkgdir" + ln -s ../../../bin/lit "$subpkgdir"/$_prefix/bin/lit +} + +_common_subpkg() { + if [ "$_default_llvm" = yes ]; then + replaces="llvm${subpkgname#$pkgname}" + provides="$replaces=$pkgver-r$pkgrel" + fi +} + +_mv() { + local dest; for dest; do true; done # get last argument + mkdir -p "$dest" + mv $@ +} + +sha512sums="82e120be5cabdfd5111aebbea68a663fe229c8861d73802d6ab09a3bf48f60de333e07e61f8fb61beaa14ac2bea24fcd74fa6f761acaf62469f536b79fcb1e16 llvm-8.0.1.src.tar.xz +f84cd65d7042e89826ba6e8d48c4c302bf4980da369d7f19a55f217e51c00ca8ed178d453df3a3cee76598a7cecb94aed0775a6d24fe73266f82749913fc3e71 llvm-fix-build-with-musl-libc.patch +49c47f125014b60d0ea7870f981a2c1708ad705793f89287ed846ee881a837a4dc0170bf467e03f2ef56177473128945287749ac80dc2d13cfabcf8b929ba58a disable-FileSystemTest.CreateDir-perms-assert.patch +caeec8e4dbd92f5f74940780b69075f3879a267a8623822cbdc193fd14706eb089071e3a5a20d60cc2eca59e4c5b2a61d29827a2f3362ee7c5f74f11d9ace200 disable-dlclose-test.patch +e5ddbc4b6c4928e79846dc3c022eb7928aaa8fed40515c78f5f03b8ab8264f34f1eb8aa8bfc0f436450932f4917e54ad261603032092ea271d9590f11a37cf1e musl-ppc64-elfv2.patch +7ba7f5b396e1afb49ea53fdc16729f0709fbba88de433cc8a8e2f751d13733011d4121318f68d7f8a16a6c57c3a1bee727cc3e0da0f5c6cae38eff70d3a539cf more-secure-plt.patch +deb71762721ebc73bfdf23143b582f40c70eddcef3e337ed14499e8e336bee2906292d38d64fe98fa633430c1bcb66cf6a2e067258c8fbe6e931f99f6d10a6f7 even-more-secure-plt.patch +53cc0d13dd871e9b775bb4e7567de4f9a97d91b8246cd7ce74607fd88d6e3e2ab9455f5b4195bc7f9dbdedbc77d659d43e98ec0b7cd78cd395aaea6919510287 python3-test.patch +4422a83ea953a6b30cb447a448d246956abd6b0cbd2451247e5f2c41318b2c0d18c7b6781155ea40a5558bbd66e9e1482cec0875d95776545fd0d87356b5e4bd scc-insertion.patch +c9ef3cd95c4bd1d6ac69bbcd471b01755126d00f59d27d4a2a2ef5623943be73f8407e2fd731294d1a9d81a66e459f45f3f1d5dc5f9646f4f2fb2d8d891b5279 fix-memory-mf_exec-on-aarch64.patch" diff --git a/legacy/llvm8/disable-FileSystemTest.CreateDir-perms-assert.patch b/legacy/llvm8/disable-FileSystemTest.CreateDir-perms-assert.patch new file mode 100644 index 000000000..e73ce9b6f --- /dev/null +++ b/legacy/llvm8/disable-FileSystemTest.CreateDir-perms-assert.patch @@ -0,0 +1,61 @@ +Do not assert permissions of file created in /tmp directory. + +This assertion fails, probably due to some specific setup of /tmp +on build servers. + + FAIL: LLVM-Unit :: Support/SupportTests/FileSystemTest.CreateDir (1293 of 17222) + ******************** TEST 'LLVM-Unit :: Support/SupportTests/FileSystemTest.CreateDir' FAILED ******************** + Note: Google Test filter = FileSystemTest.CreateDir + [==========] Running 1 test from 1 test case. + [----------] Global test environment set-up. + [----------] 1 test from FileSystemTest + [ RUN ] FileSystemTest.CreateDir + /home/buildozer/aports/testing/llvm3.9/src/llvm-3.9.1.src/unittests/Support/Path.cpp:591: Failure + Value of: fs::perms::owner_read | fs::perms::owner_exe + Actual: 320 + Expected: Status.permissions() & fs::perms::all_all + Which is: 448 + +--- a/unittests/Support/Path.cpp ++++ b/unittests/Support/Path.cpp +@@ -579,23 +579,23 @@ + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); + + #ifdef LLVM_ON_UNIX +- // Set a 0000 umask so that we can test our directory permissions. +- mode_t OldUmask = ::umask(0000); +- +- fs::file_status Status; +- ASSERT_NO_ERROR( +- fs::create_directory(Twine(TestDirectory) + "baz500", false, +- fs::perms::owner_read | fs::perms::owner_exe)); +- ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz500", Status)); +- ASSERT_EQ(Status.permissions() & fs::perms::all_all, +- fs::perms::owner_read | fs::perms::owner_exe); +- ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "baz777", false, +- fs::perms::all_all)); +- ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz777", Status)); +- ASSERT_EQ(Status.permissions() & fs::perms::all_all, fs::perms::all_all); +- +- // Restore umask to be safe. +- ::umask(OldUmask); ++// // Set a 0000 umask so that we can test our directory permissions. ++// mode_t OldUmask = ::umask(0000); ++// ++// fs::file_status Status; ++// ASSERT_NO_ERROR( ++// fs::create_directory(Twine(TestDirectory) + "baz500", false, ++// fs::perms::owner_read | fs::perms::owner_exe)); ++// ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz500", Status)); ++// ASSERT_EQ(Status.permissions() & fs::perms::all_all, ++// fs::perms::owner_read | fs::perms::owner_exe); ++// ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "baz777", false, ++// fs::perms::all_all)); ++// ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz777", Status)); ++// ASSERT_EQ(Status.permissions() & fs::perms::all_all, fs::perms::all_all); ++// ++// // Restore umask to be safe. ++// ::umask(OldUmask); + #endif + + #ifdef LLVM_ON_WIN32 diff --git a/legacy/llvm8/disable-dlclose-test.patch b/legacy/llvm8/disable-dlclose-test.patch new file mode 100644 index 000000000..b70cd4d4d --- /dev/null +++ b/legacy/llvm8/disable-dlclose-test.patch @@ -0,0 +1,18 @@ +--- llvm-6.0.1.src/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp.old 2017-07-12 21:22:45.000000000 +0000 ++++ llvm-6.0.1.src/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp 2018-09-13 04:43:37.240000000 +0000 +@@ -107,6 +107,7 @@ + EXPECT_TRUE(DynamicLibrary::SearchOrder == DynamicLibrary::SO_Linker); + } + ++#if 0 + TEST(DynamicLibrary, Shutdown) { + std::string A("PipSqueak"), B, C("SecondLib"); + std::vector<std::string> Order; +@@ -162,6 +163,7 @@ + EXPECT_EQ(Order.front(), "SecondLib"); + EXPECT_EQ(Order.back(), "PipSqueak"); + } ++#endif + + #else + diff --git a/legacy/llvm8/even-more-secure-plt.patch b/legacy/llvm8/even-more-secure-plt.patch new file mode 100644 index 000000000..112e111b8 --- /dev/null +++ b/legacy/llvm8/even-more-secure-plt.patch @@ -0,0 +1,101 @@ +Index: lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +=================================================================== +--- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp ++++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +@@ -442,13 +442,22 @@ + // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must + // come at the _end_ of the expression. + const MCOperand &Op = MI->getOperand(OpNo); +- const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr()); +- O << refExp.getSymbol().getName(); ++ const MCSymbolRefExpr *RefExp = nullptr; ++ const MCConstantExpr *ConstExp = nullptr; ++ if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Op.getExpr())) { ++ RefExp = cast<MCSymbolRefExpr>(BinExpr->getLHS()); ++ ConstExp = cast<MCConstantExpr>(BinExpr->getRHS()); ++ } else ++ RefExp = cast<MCSymbolRefExpr>(Op.getExpr()); ++ ++ O << RefExp->getSymbol().getName(); + O << '('; + printOperand(MI, OpNo+1, O); + O << ')'; +- if (refExp.getKind() != MCSymbolRefExpr::VK_None) +- O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind()); ++ if (RefExp->getKind() != MCSymbolRefExpr::VK_None) ++ O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind()); ++ if (ConstExp != nullptr) ++ O << '+' << ConstExp->getValue(); + } + + /// showRegistersWithPercentPrefix - Check if this register name should be +Index: lib/Target/PowerPC/PPCAsmPrinter.cpp +=================================================================== +--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp ++++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp +@@ -487,8 +487,14 @@ + if (!Subtarget->isPPC64() && !Subtarget->isDarwin() && + isPositionIndependent()) + Kind = MCSymbolRefExpr::VK_PLT; +- const MCSymbolRefExpr *TlsRef = ++ const MCExpr *TlsRef = + MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext); ++ ++ // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI. ++ if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt()) ++ TlsRef = MCBinaryExpr::createAdd(TlsRef, ++ MCConstantExpr::create(32768, OutContext), ++ OutContext); + const MachineOperand &MO = MI->getOperand(2); + const GlobalValue *GValue = MO.getGlobal(); + MCSymbol *MOSymbol = getSymbol(GValue); +Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp +=================================================================== +--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp ++++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +@@ -4054,7 +4054,20 @@ + if (trySETCC(N)) + return; + break; +- ++ // These nodes will be transformed into GETtlsADDR32 node, which ++ // later becomes BL_TLS __tls_get_addr(sym at tlsgd)@PLT ++ case PPCISD::ADDI_TLSLD_L_ADDR: ++ case PPCISD::ADDI_TLSGD_L_ADDR: { ++ const Module *Mod = MF->getFunction().getParent(); ++ if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || ++ !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || ++ Mod->getPICLevel() == PICLevel::SmallPIC) ++ break; ++ // Attach global base pointer on GETtlsADDR32 node in order to ++ // generate secure plt code for TLS symbols. ++ getGlobalBaseReg(); ++ } ++ break; + case PPCISD::CALL: { + const Module *M = MF->getFunction().getParent(); + +Index: test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll +=================================================================== +--- a/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll ++++ b/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll +@@ -0,0 +1,18 @@ ++; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=SECURE-PLT-TLS %s ++ ++@a = thread_local local_unnamed_addr global i32 6, align 4 ++define i32 @main() local_unnamed_addr #0 { ++entry: ++ %0 = load i32, i32* @a, align 4 ++ ret i32 %0 ++} ++ ++ ++!llvm.module.flags = !{!0} ++!0 = !{i32 7, !"PIC Level", i32 2} ++ ++; SECURE-PLT-TLS: mflr 30 ++; SECURE-PLT-TLS-NEXT: addis 30, 30, .LTOC-.L0$pb@ha ++; SECURE-PLT-TLS-NEXT: addi 30, 30, .LTOC-.L0$pb@l ++; SECURE-PLT-TLS-NEXT: bl .L{{.*}} ++; SECURE-PLT-TLS: bl __tls_get_addr(a@tlsgd)@PLT+32768 +\ No newline at end of file diff --git a/legacy/llvm8/fix-memory-mf_exec-on-aarch64.patch b/legacy/llvm8/fix-memory-mf_exec-on-aarch64.patch new file mode 100644 index 000000000..a70b39733 --- /dev/null +++ b/legacy/llvm8/fix-memory-mf_exec-on-aarch64.patch @@ -0,0 +1,33 @@ +Fix failures in AllocationTests/MappedMemoryTest.* on aarch64: + + Failing Tests (8): + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.AllocAndRelease/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.DuplicateNear/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.EnabledWrite/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.MultipleAllocAndRelease/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.SuccessiveNear/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.UnalignedNear/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.ZeroNear/3 + LLVM-Unit :: Support/./SupportTests/AllocationTests/MappedMemoryTest.ZeroSizeNear/3 + +Upstream-Issue: https://bugs.llvm.org/show_bug.cgi?id=14278#c10 + +--- a/lib/Support/Unix/Memory.inc ++++ b/lib/Support/Unix/Memory.inc +@@ -54,7 +54,7 @@ + llvm::sys::Memory::MF_EXEC: + return PROT_READ | PROT_WRITE | PROT_EXEC; + case llvm::sys::Memory::MF_EXEC: +-#if defined(__FreeBSD__) ++#if defined(__FreeBSD__) || (defined(__linux__) && (defined(__aarch64__) || defined(__powerpc64__))) + // On PowerPC, having an executable page that has no read permission + // can have unintended consequences. The function InvalidateInstruction- + // Cache uses instructions dcbf and icbi, both of which are treated by +@@ -62,6 +62,7 @@ + // executing these instructions will result in a segmentation fault. + // Somehow, this problem is not present on Linux, but it does happen + // on FreeBSD. ++ // The same problem is present even on aarch64 Linux (at least on musl). + return PROT_READ | PROT_EXEC; + #else + return PROT_EXEC; diff --git a/legacy/llvm8/llvm-fix-build-with-musl-libc.patch b/legacy/llvm8/llvm-fix-build-with-musl-libc.patch new file mode 100644 index 000000000..6ee91ea44 --- /dev/null +++ b/legacy/llvm8/llvm-fix-build-with-musl-libc.patch @@ -0,0 +1,46 @@ +From 5c571082fdaf61f6df19d9b7137dc26d71334058 Mon Sep 17 00:00:00 2001 +From: Natanael Copa <ncopa@alpinelinux.org> +Date: Thu, 18 Feb 2016 10:33:04 +0100 +Subject: [PATCH 2/3] Fix build with musl libc + +On musl libc the fopen64 and fopen are the same thing, but for +compatibility they have a `#define fopen64 fopen`. Same applies for +fseek64, fstat64, fstatvfs64, ftello64, lstat64, stat64 and tmpfile64. +--- + include/llvm/Analysis/TargetLibraryInfo.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h +index 7becdf0..7f14427 100644 +--- a/include/llvm/Analysis/TargetLibraryInfo.h ++++ b/include/llvm/Analysis/TargetLibraryInfo.h +@@ -18,6 +18,26 @@ + #include "llvm/IR/Module.h" + #include "llvm/Pass.h" + ++#undef fopen64 ++#undef fseeko64 ++#undef fstat64 ++#undef fstatvfs64 ++#undef ftello64 ++#undef lstat64 ++#undef stat64 ++#undef tmpfile64 ++#undef F_GETLK64 ++#undef F_SETLK64 ++#undef F_SETLKW64 ++#undef flock64 ++#undef open64 ++#undef openat64 ++#undef creat64 ++#undef lockf64 ++#undef posix_fadvise64 ++#undef posix_fallocate64 ++#undef off64_t ++ + namespace llvm { + /// VecDesc - Describes a possible vectorization of a function. + /// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized +-- +2.7.3 + diff --git a/legacy/llvm8/more-secure-plt.patch b/legacy/llvm8/more-secure-plt.patch new file mode 100644 index 000000000..8b18a6db2 --- /dev/null +++ b/legacy/llvm8/more-secure-plt.patch @@ -0,0 +1,145 @@ +--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp ++++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -2769,8 +2769,12 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, + SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64); + GOTPtr = DAG.getNode(PPCISD::ADDIS_GOT_TPREL_HA, dl, + PtrVT, GOTReg, TGA); +- } else +- GOTPtr = DAG.getNode(PPCISD::PPC32_GOT, dl, PtrVT); ++ } else { ++ if (isPositionIndependent()) ++ GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); ++ else ++ GOTPtr = DAG.getNode(PPCISD::PPC32_GOT, dl, PtrVT); ++ } + SDValue TPOffset = DAG.getNode(PPCISD::LD_GOT_TPREL_L, dl, + PtrVT, TGA, GOTPtr); + return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TPOffset, TGATLS); +@@ -4941,7 +4945,8 @@ PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, SDValue &Chain, + if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) + GV = G->getGlobal(); + bool Local = TM.shouldAssumeDSOLocal(*Mod, GV); +- bool UsePlt = !Local && Subtarget.isTargetELF() && !isPPC64; ++ bool UsePlt = !Local && Subtarget.isTargetELF() && !isPPC64 && ++ TM.isPositionIndependent(); + + if (isFunctionGlobalAddress(Callee)) { + GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Callee); +--- llvm/lib/Target/PowerPC/PPCSubtarget.cpp ++++ llvm/lib/Target/PowerPC/PPCSubtarget.cpp +@@ -138,7 +138,8 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { + if (isDarwin()) + HasLazyResolverStubs = true; + +- if (TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD()) ++ if (TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD() || ++ TargetTriple.isMusl()) + SecurePlt = true; + + if (HasSPE && IsPPC64) +--- llvm/test/CodeGen/PowerPC/2008-10-28-f128-i32.ll ++++ llvm/test/CodeGen/PowerPC/2008-10-28-f128-i32.ll +@@ -62,7 +62,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: lfd 4, 328(1) + ; CHECK-NEXT: fmr 1, 31 + ; CHECK-NEXT: fmr 2, 30 +-; CHECK-NEXT: bl __gcc_qmul@PLT ++; CHECK-NEXT: bl __gcc_qmul + ; CHECK-NEXT: lis 3, 16864 + ; CHECK-NEXT: stfd 1, 280(1) + ; CHECK-NEXT: fmr 29, 1 +@@ -84,7 +84,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: lfd 4, 360(1) + ; CHECK-NEXT: lfd 1, 352(1) + ; CHECK-NEXT: lfd 2, 344(1) +-; CHECK-NEXT: bl __gcc_qsub@PLT ++; CHECK-NEXT: bl __gcc_qsub + ; CHECK-NEXT: mffs 0 + ; CHECK-NEXT: mtfsb1 31 + ; CHECK-NEXT: lis 3, .LCPI0_1@ha +@@ -117,7 +117,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: .LBB0_5: # %bb1 + ; CHECK-NEXT: li 4, 0 + ; CHECK-NEXT: mr 3, 30 +-; CHECK-NEXT: bl __floatditf@PLT ++; CHECK-NEXT: bl __floatditf + ; CHECK-NEXT: lis 3, 17392 + ; CHECK-NEXT: stfd 1, 208(1) + ; CHECK-NEXT: fmr 29, 1 +@@ -140,7 +140,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: lfd 4, 232(1) + ; CHECK-NEXT: lfd 1, 224(1) + ; CHECK-NEXT: lfd 2, 216(1) +-; CHECK-NEXT: bl __gcc_qadd@PLT ++; CHECK-NEXT: bl __gcc_qadd + ; CHECK-NEXT: blt 2, .LBB0_7 + ; CHECK-NEXT: # %bb.6: # %bb1 + ; CHECK-NEXT: fmr 2, 28 +@@ -163,7 +163,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: stw 3, 248(1) + ; CHECK-NEXT: lfd 3, 256(1) + ; CHECK-NEXT: lfd 4, 248(1) +-; CHECK-NEXT: bl __gcc_qsub@PLT ++; CHECK-NEXT: bl __gcc_qsub + ; CHECK-NEXT: stfd 2, 176(1) + ; CHECK-NEXT: fcmpu 0, 2, 27 + ; CHECK-NEXT: stfd 1, 168(1) +@@ -205,7 +205,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: lfd 4, 72(1) + ; CHECK-NEXT: lfd 1, 64(1) + ; CHECK-NEXT: lfd 2, 56(1) +-; CHECK-NEXT: bl __gcc_qsub@PLT ++; CHECK-NEXT: bl __gcc_qsub + ; CHECK-NEXT: mffs 0 + ; CHECK-NEXT: mtfsb1 31 + ; CHECK-NEXT: lis 3, .LCPI0_2@ha +@@ -260,7 +260,7 @@ define i64 @__fixunstfdi(ppc_fp128 %a) nounwind readnone { + ; CHECK-NEXT: lfd 4, 136(1) + ; CHECK-NEXT: lfd 1, 128(1) + ; CHECK-NEXT: lfd 2, 120(1) +-; CHECK-NEXT: bl __gcc_qsub@PLT ++; CHECK-NEXT: bl __gcc_qsub + ; CHECK-NEXT: mffs 0 + ; CHECK-NEXT: mtfsb1 31 + ; CHECK-NEXT: lis 3, .LCPI0_0@ha +--- llvm/test/CodeGen/PowerPC/2010-02-12-saveCR.ll ++++ llvm/test/CodeGen/PowerPC/2010-02-12-saveCR.ll +@@ -11,7 +11,7 @@ entry: + ; CHECK-DAG: ori [[T2:[0-9]+]], [[T2]], 34492 + ; CHECK-DAG: stwx [[T1]], 1, [[T2]] + ; CHECK-DAG: addi 3, 1, 28 +-; CHECK: bl bar@PLT ++; CHECK: bl bar + %x = alloca [100000 x i8] ; <[100000 x i8]*> [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] + %x1 = bitcast [100000 x i8]* %x to i8* ; <i8*> [#uses=1] +--- llvm/test/CodeGen/PowerPC/available-externally.ll ++++ llvm/test/CodeGen/PowerPC/available-externally.ll +@@ -14,7 +14,7 @@ target triple = "powerpc-unknown-linux-gnu" + define i32 @foo(i64 %x) nounwind { + entry: + ; STATIC: foo: +-; STATIC: bl exact_log2@PLT ++; STATIC: bl exact_log2 + ; STATIC: blr + + ; PIC: foo: +--- llvm/test/CodeGen/PowerPC/stubs.ll ++++ llvm/test/CodeGen/PowerPC/stubs.ll +@@ -6,4 +6,4 @@ entry: + } + + ; CHECK: test1: +-; CHECK: bl __floatditf@PLT ++; CHECK: bl __floatditf +--- llvm/test/CodeGen/PowerPC/umulo-128-legalisation-lowering.ll ++++ llvm/test/CodeGen/PowerPC/umulo-128-legalisation-lowering.ll +@@ -72,7 +72,7 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 { + ; PPC32-NEXT: mr 28, 9 + ; PPC32-NEXT: mr 23, 6 + ; PPC32-NEXT: mr 24, 5 +-; PPC32-NEXT: bl __multi3@PLT ++; PPC32-NEXT: bl __multi3 + ; PPC32-NEXT: mr 7, 4 + ; PPC32-NEXT: mullw 4, 24, 30 + ; PPC32-NEXT: mullw 8, 29, 23 diff --git a/legacy/llvm8/musl-ppc64-elfv2.patch b/legacy/llvm8/musl-ppc64-elfv2.patch new file mode 100644 index 000000000..016be5dad --- /dev/null +++ b/legacy/llvm8/musl-ppc64-elfv2.patch @@ -0,0 +1,43 @@ +From 750d323a6060ad92c3d247f85d6555041f55b4a5 Mon Sep 17 00:00:00 2001 +From: "A. Wilcox" <AWilcox@Wilcox-Tech.com> +Date: Thu, 4 Oct 2018 15:26:59 -0500 +Subject: [PATCH] Add support for powerpc64-*-linux-musl targets + +This patch ensures that 64-bit PowerPC musl targets use ELFv2 ABI on both +endians. It additionally adds a test that big endian PPC64 uses ELFv2 on +musl. +--- + lib/Target/PowerPC/PPCTargetMachine.cpp | 4 ++++ + test/CodeGen/PowerPC/ppc64-elf-abi.ll | 1 + + 2 files changed, 5 insertions(+) + +diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp +index 34410393ef6..c583fba8cab 100644 +--- a/lib/Target/PowerPC/PPCTargetMachine.cpp ++++ b/lib/Target/PowerPC/PPCTargetMachine.cpp +@@ -199,6 +199,10 @@ static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, + case Triple::ppc64le: + return PPCTargetMachine::PPC_ABI_ELFv2; + case Triple::ppc64: ++ // musl uses ELFv2 ABI on both endians. ++ if (TT.getEnvironment() == Triple::Musl) ++ return PPCTargetMachine::PPC_ABI_ELFv2; ++ + return PPCTargetMachine::PPC_ABI_ELFv1; + default: + return PPCTargetMachine::PPC_ABI_UNKNOWN; +diff --git a/test/CodeGen/PowerPC/ppc64-elf-abi.ll b/test/CodeGen/PowerPC/ppc64-elf-abi.ll +index 1e17930304b..aa594b37b47 100644 +--- a/test/CodeGen/PowerPC/ppc64-elf-abi.ll ++++ b/test/CodeGen/PowerPC/ppc64-elf-abi.ll +@@ -1,6 +1,7 @@ + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu < %s | FileCheck %s -check-prefix=CHECK-ELFv1 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -target-abi elfv1 < %s | FileCheck %s -check-prefix=CHECK-ELFv1 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -target-abi elfv2 < %s | FileCheck %s -check-prefix=CHECK-ELFv2 ++; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-musl < %s | FileCheck %s -check-prefix=CHECK-ELFv2 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s -check-prefix=CHECK-ELFv2 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -target-abi elfv1 < %s | FileCheck %s -check-prefix=CHECK-ELFv1 + ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -target-abi elfv2 < %s | FileCheck %s -check-prefix=CHECK-ELFv2 +-- +2.18.0 + diff --git a/legacy/llvm8/python3-test.patch b/legacy/llvm8/python3-test.patch new file mode 100644 index 000000000..746313317 --- /dev/null +++ b/legacy/llvm8/python3-test.patch @@ -0,0 +1,8 @@ +--- llvm-7.0.1.src/test/BugPoint/compile-custom.ll.py.old 2014-03-13 00:10:37.000000000 +0000 ++++ llvm-7.0.1.src/test/BugPoint/compile-custom.ll.py 2019-03-10 03:48:48.600000000 +0000 +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + + import sys + diff --git a/legacy/llvm8/scc-insertion.patch b/legacy/llvm8/scc-insertion.patch new file mode 100644 index 000000000..b2d7d511a --- /dev/null +++ b/legacy/llvm8/scc-insertion.patch @@ -0,0 +1,33 @@ +From f7e9f4f4c50245d10ca9869a9f8f3d431dfb6948 Mon Sep 17 00:00:00 2001 +From: Warren Ristow <warren_ristow@playstation.sony.com> +Date: Tue, 14 Jan 2020 10:30:24 -0800 +Subject: [PATCH] SCC: Allow ReplaceNode to safely support insertion + +If scc_iterator::ReplaceNode is inserting a new entry in the map, +rather than replacing an existing entry, the possibility of growing +the map could cause a failure. This change safely implements the +insertion. + +Reviewed By: probinson + +Differential Revision: https://reviews.llvm.org/D72469 +--- + include/llvm/ADT/SCCIterator.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h +index eb1a5d0938cf..1e642b9f75d3 100644 +--- a/include/llvm/ADT/SCCIterator.h ++++ b/include/llvm/ADT/SCCIterator.h +@@ -134,7 +134,10 @@ class scc_iterator : public iterator_facade_base< + /// has been deleted, and \c New is to be used in its place. + void ReplaceNode(NodeRef Old, NodeRef New) { + assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?"); +- nodeVisitNumbers[New] = nodeVisitNumbers[Old]; ++ // Do the assignment in two steps, in case 'New' is not yet in the map, and ++ // inserting it causes the map to grow. ++ auto tempVal = nodeVisitNumbers[Old]; ++ nodeVisitNumbers[New] = tempVal; + nodeVisitNumbers.erase(Old); + } + }; diff --git a/legacy/lxmenu-data/APKBUILD b/legacy/lxmenu-data/APKBUILD new file mode 100644 index 000000000..9e60933b9 --- /dev/null +++ b/legacy/lxmenu-data/APKBUILD @@ -0,0 +1,34 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=lxmenu-data +pkgver=0.1.5 +pkgrel=1 +pkgdesc="Menu definition files for LXQt" +url="https://lxqt.github.io/" +arch="noarch" +options="!check" # No test suite. +license="LGPL-2.1+" +depends="" +makedepends="automake autoconf glib-dev intltool" +source="lxmenu-data-$pkgver.tar.gz::https://github.com/lxde/lxmenu-data/archive/$pkgver.tar.gz" + +prepare() { + default_prepare + ./autogen.sh +} + +build() { + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man + make +} + +package() { + make DESTDIR="$pkgdir" install +} + +sha512sums="78c56666a3d8c1e6bc7cadd4f1f9ba3236def216676808f4fa19663bf93ce59ea5b2591b20ad40373167ee3e37634844e20a2e20e445e52b255d3fbfda23f8f3 lxmenu-data-0.1.5.tar.gz" diff --git a/legacy/lxqt-l10n/APKBUILD b/legacy/lxqt-l10n/APKBUILD new file mode 100644 index 000000000..35b44c8d6 --- /dev/null +++ b/legacy/lxqt-l10n/APKBUILD @@ -0,0 +1,35 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=lxqt-l10n +pkgver=0.13.0 +pkgrel=1 +pkgdesc="Localization files for LXQt" +url="https://lxqt.github.io/" +arch="noarch" +options="!check" # No test suite. +license="LGPL-2.1+" +depends="" +makedepends="cmake extra-cmake-modules qt5-qttools-dev liblxqt-dev libqtxdg-dev + lxqt-build-tools>=0.5.0" +source="https://github.com/lxde/lxqt-l10n/releases/download/$pkgver/lxqt-l10n-$pkgver.tar.xz" + +build() { + if [ "$CBUILD" != "$CHOST" ]; then + CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" + fi + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DBUILD_SHARED_LIBS=True \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ + -DCMAKE_C_FLAGS="$CFLAGS" \ + ${CMAKE_CROSSOPTS} -Bbuild + make -C build +} + +package() { + make DESTDIR="$pkgdir" -C build install +} + +sha512sums="cbafc0f1c12a9c14af8ed896f5147d90fcd24786be0cc5de7f8897e31ac012a7308604622635f43709edeb13824395806e6d8e89355a0fd6799227f8d0d8f686 lxqt-l10n-0.13.0.tar.xz" diff --git a/legacy/mach64-drm/APKBUILD b/legacy/mach64-drm/APKBUILD new file mode 100644 index 000000000..96fe34b04 --- /dev/null +++ b/legacy/mach64-drm/APKBUILD @@ -0,0 +1,33 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +_kver="5.4.66-mc1" +pkgname=mach64-drm +pkgver=5.6 +pkgrel=0 +pkgdesc="Kernel driver for Mach64 GPUs" +url=" " +arch="pmmx ppc" +options="!check !dbg !strip" # No test suite. +license="MIT" +depends="easy-kernel-modules-$_kver" +makedepends="easy-kernel-src-$_kver" +subpackages="" +source="mach64-drm-$pkgver.tar.gz::https://github.com/trya/mach64-drm/archive/v$pkgver.tar.gz + header-fix.patch + " + +build() { + make -C /usr/src/linux-$_kver M="$builddir" modules +} + +package() { + if [ -f $HOME/kernel_key.pem ]; then + /usr/src/linux-$_kver/scripts/sign-file sha512 \ + $HOME/kernel_key.pem $HOME/kernel_key.pem \ + "$builddir"/mach64.ko + fi + make -C /usr/src/linux-$_kver DEPMOD=true INSTALL_MOD_PATH="$pkgdir" M="$builddir" modules_install +} + +sha512sums="c130a93e9a578943dbdfeb31040165cba3534014bf32fb6670b688ec464d6e83e781556d4b320127e0d95ad0c30c573f667cd8e9d6cd210d0edad14faedba75f mach64-drm-5.6.tar.gz +2262aedb693fcba9110ad07775b4524313d16032e5afdb23bfb610ce7ee242293c282abf6d11d528b7a0d226439a08877f432f1bde04df7cb5ce503ced02ffa6 header-fix.patch" diff --git a/legacy/mach64-drm/header-fix.patch b/legacy/mach64-drm/header-fix.patch new file mode 100644 index 000000000..797bf8194 --- /dev/null +++ b/legacy/mach64-drm/header-fix.patch @@ -0,0 +1,10 @@ +--- mach64-drm-5.6/mach64_drv.c.old 2020-04-24 00:36:27.000000000 +0000 ++++ mach64-drm-5.6/mach64_drv.c 2020-08-09 20:03:14.816701578 +0000 +@@ -32,6 +32,7 @@ + + #include <drm/drm_drv.h> + #include <drm/drm_file.h> ++#include <drm/drm_pci.h> + + #include "mach64_drm.h" + #include "mach64_drv.h" diff --git a/legacy/man-db/APKBUILD b/legacy/man-db/APKBUILD new file mode 100644 index 000000000..136e0720d --- /dev/null +++ b/legacy/man-db/APKBUILD @@ -0,0 +1,44 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=man-db +pkgver=2.9.1 +pkgrel=0 +pkgdesc="The man command and related utilities for examining on-line help files" +url="https://www.nongnu.org/man-db/" +arch="all" +options="!check" # requires //IGNORE in iconv +license="GPL-2.0+" +depends="groff gzip less" +makedepends_host="db-dev libpipeline-dev zlib-dev" +subpackages="$pkgname-doc $pkgname-lang" +triggers="man-db.trigger=/usr/share/man" +source="https://download.savannah.nongnu.org/releases/man-db/man-db-$pkgver.tar.xz + man-db-2.8.5-iconv.patch + " + +build() { + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var \ + --disable-setuid \ + --with-sections="1 1p 1x 2 2x 3 3p 3x 4 4x 5 5x 6 6x 7 7x 8 8x 9 0p tcl n l p o" \ + --enable-nls \ + --with-db=db + make +} + +check() { + make check +} + +package() { + make DESTDIR="$pkgdir" install + rm -r "${pkgdir}"/usr/lib/tmpfiles.d # systemd +} + +sha512sums="ae2d1e9f293795c63f5a9a1a765478a9a59cbe5fe6f759647be5057c1ae53f90baee8d5467921f3d0102300f2111a5026eeb25f78401bcb16ce45ad790634977 man-db-2.9.1.tar.xz +0a68260fc48488408dc11855858aa2569efa3aeefd765c425b8fc988e7fee3e1d42e19eb299e518afc9b2ae54c5d37911176127124a43d5041f1137af0457097 man-db-2.8.5-iconv.patch" diff --git a/legacy/man-db/man-db-2.8.5-iconv.patch b/legacy/man-db/man-db-2.8.5-iconv.patch new file mode 100644 index 000000000..c2232920d --- /dev/null +++ b/legacy/man-db/man-db-2.8.5-iconv.patch @@ -0,0 +1,65 @@ +--- man-db-2.8.5/src/man.c 2018-06-18 22:44:35.672743065 -0500 ++++ man-db-2.8.5/src/man.c 2018-06-18 22:46:35.032624890 -0500 +@@ -1516,15 +1516,13 @@ + { + debug ("add_output_iconv: source %s, target %s\n", source, target); + if (source && target && !STREQ (source, target)) { +- char *target_translit = xasprintf ("%s//TRANSLIT", target); + pipecmd *iconv_cmd; + iconv_cmd = pipecmd_new_args +- ("iconv", "-c", "-f", source, "-t", target_translit, ++ ("iconv", "-c", "-f", source, "-t", target, + (void *) 0); + pipecmd_pre_exec (iconv_cmd, sandbox_load, sandbox_free, + sandbox); + pipeline_command (p, iconv_cmd); +- free (target_translit); + } + } + +--- man-db-2.8.5/src/manconv.c ++++ man-db-2.8.5/src/manconv.c +@@ -111,6 +111,5 @@ static int try_iconv (pipeline *p, const char *try_from_code, const char *to, + iconv_t cd_utf8, cd = NULL; +- bool to_utf8 = STREQ (try_to_code, "UTF-8") || +- STRNEQ (try_to_code, "UTF-8//", 7); +- const char *utf8_target = last ? "UTF-8//IGNORE" : "UTF-8"; +- bool ignore_errors = (strstr (try_to_code, "//IGNORE") != NULL); ++ bool to_utf8 = STREQ (try_to_code, "UTF-8"); ++ const char *utf8_target = "UTF-8"; ++ bool ignore_errors = 0; + int ret = 0; +--- man-db-2.8.5/src/manconv_client.c ++++ man-db-2.8.5/src/manconv_client.c +@@ -102,7 +102,7 @@ void add_manconv (pipeline *p, const char *source, const char *target) + codes->from[2] = NULL; + name = appendstr (name, "UTF-8:", source, (void *) 0); + } +- codes->to = xasprintf ("%s//IGNORE", target); ++ codes->to = xstrdup (target); + /* informational only; no shell quoting concerns */ + name = appendstr (name, " -t ", codes->to, (void *) 0); + if (quiet >= 2) +--- man-db-2.8.5/src/manconv_main.c ++++ man-db-2.8.5/src/manconv_main.c +@@ -106,9 +106,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) + return 0; + case 't': + to_code = xstrdup (arg); +- if (!strstr (to_code, "//")) +- to_code = appendstr (to_code, "//TRANSLIT", +- (void *) 0); + return 0; + case 'd': + debug_level = 1; +--- man-db-2.8.5/src/whatis.c ++++ man-db-2.8.5/src/whatis.c +@@ -945,7 +945,7 @@ int main (int argc, char *argv[]) + display_seen = hashtable_create (&null_hashtable_free); + + #ifdef HAVE_ICONV +- locale_charset = xasprintf ("%s//IGNORE", get_locale_charset ()); ++ locale_charset = xstrdup (get_locale_charset ()); + conv_to_locale = iconv_open (locale_charset, "UTF-8"); + free (locale_charset); + #endif /* HAVE_ICONV */ diff --git a/legacy/man-db/man-db.trigger b/legacy/man-db/man-db.trigger new file mode 100644 index 000000000..f9de5961c --- /dev/null +++ b/legacy/man-db/man-db.trigger @@ -0,0 +1,3 @@ +#!/bin/sh + +exec /usr/bin/mandb /usr/share/man >/dev/null diff --git a/legacy/minizip-ng/APKBUILD b/legacy/minizip-ng/APKBUILD new file mode 100644 index 000000000..7e60b5857 --- /dev/null +++ b/legacy/minizip-ng/APKBUILD @@ -0,0 +1,32 @@ +# Maintainer: Zach van Rijn <me@zv.io> +pkgname=minizip-ng +pkgver=3.0.6 +pkgrel=0 +pkgdesc="A zip manipulation library written in C, derived from Mark Adler's implementation" +url="https://github.com/zlib-ng/minizip-ng/wiki" +arch="all" +license="Zlib" +depends="" +makedepends="cmake libtool zlib-dev" +subpackages="$pkgname-dev" +source="$pkgname-$pkgver.tar.gz::https://github.com/zlib-ng/minizip-ng/archive/refs/tags/${pkgver}.tar.gz" + +build() { + cmake . \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DBUILD_SHARED_LIBS=ON \ + -DMZ_BUILD_TESTS=ON + make +} + +check() { + ./test_cmd +} + +package() { + make DESTDIR="$pkgdir" install +} + +sha512sums="92aaad655e7dbec60ab8075435ccdc72314f75f0516aa4a16094215df2b14b108c2b49cdf6c876e396f0f43f52ad63f52ce7db2e119efe25c55b8b873bef9d4f minizip-ng-3.0.6.tar.gz" diff --git a/legacy/mistserver/APKBUILD b/legacy/mistserver/APKBUILD new file mode 100644 index 000000000..093d88f4e --- /dev/null +++ b/legacy/mistserver/APKBUILD @@ -0,0 +1,72 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=mistserver +pkgver=3.1 +pkgrel=0 +pkgdesc="Multimedia streaming services" +url="https://mistserver.org" +arch="all" +options="" +license="Zlib AND AGPL-3.0-only" +depends="" +install="$pkgname.pre-install" +makedepends="cmake libexecinfo-dev mbedtls-dev libsrtp-dev" +pkgusers="mistserver" +pkggroups="mistserver" +subpackages="$pkgname-dev $pkgname-openrc" +# ATTENTION MAINTAINERS: Generate a new aggregate patch from: +# (assuming rebased on upstream correctly) +# git clone https://github.com/gizahNL/mistserver.git +# cd mistserver +# git format-patch -M origin/master --stdout > gizahnl-mbedtls-dev-from-origin-master.patch +source="mistserver-$pkgver.tar.gz::https://github.com/DDVTECH/mistserver/archive/refs/tags/$pkgver.tar.gz + mistserver.confd + mistserver.initd + link-execinfo.patch + + add-dtls-srtp-cmake-option.patch + gizahnl-mbedtls-dev-from-origin-master.patch + fix-cmake-test-format.patch + " + +build() { + if [ "$CBUILD" != "$CHOST" ]; then + CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" + fi + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DBUILD_SHARED_LIBS=True \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS -fPIC" \ + -DCMAKE_C_FLAGS="$CFLAGS -fPIC" \ + -DUSE_MBEDTLS_SSL_DTLS_SRTP=True \ + ${CMAKE_CROSSOPTS} \ + . + make -j1 # do not increase this (race conditions) +} + +check() { + # FIXME!!! + #CTEST_OUTPUT_ON_FAILURE=TRUE ctest + + # temporary sanity check + ./MistSession -v | grep Built +} + +package() { + make DESTDIR="$pkgdir" install + + # OpenRC + + install -Dm755 "$srcdir"/mistserver.initd "$pkgdir"/etc/init.d/mistserver + install -Dm644 "$srcdir"/mistserver.confd "$pkgdir"/etc/conf.d/mistserver +} + +sha512sums="efcac86cf031c5cc13dd274a4d63292122f1ef3d46faea0457e075898cda01bdea29f011699b595e07c8ed984886a33da2a04395a67698d6b2b405325f1b9715 mistserver-3.1.tar.gz +7288adab6589f2facc1cb794057b1c5d9ec94e12e60d6afc8f6f25c54a8e908cc9841b83b5a6e608fa799fd6aa11767e92a963004182d45f7be9ccd3b65097e7 mistserver.confd +e0c7df42f4d486983ece1ea50ab8f3006ebab5386881c14c4b2ff1246b6dd38ace935dc54f8f8a7687edb7ca5975b8c26abd6e99957b8c892862732263d49eb9 mistserver.initd +a27bac965078f7eafb339ae7be9e50519d5728ae4f5d725905d5eecbb3fdf048df3e150cfa881be4bab754ca674a11271343156d5d97758d2ca65bef5bff55a6 link-execinfo.patch +f90737722ac4a2ecff64386a9287ce0ddd48e7b176239f3de26725cadace52667ab44febe536738d8e0dba1fee2047e8f65caa8a2f282c7c6e9dbcc4f8daa23a add-dtls-srtp-cmake-option.patch +48e835a09b8096f78e94f25429768debf65ab9f4b3152c45b69eb072ac5d3abc0036daae894e6b85c57ad7ae7993bf2940c730fbb02dcafecd2ed9716b86dfb9 gizahnl-mbedtls-dev-from-origin-master.patch +de8bc5279426c7fab58074a4e73001c590dd386c0d7cd1747e6fff74278aa901662e7720bf97ea645eb28fc1a6c3e4830afdcaf5e4a770c996c639936dd3e28b fix-cmake-test-format.patch" diff --git a/legacy/mistserver/add-dtls-srtp-cmake-option.patch b/legacy/mistserver/add-dtls-srtp-cmake-option.patch new file mode 100644 index 000000000..8704b5a08 --- /dev/null +++ b/legacy/mistserver/add-dtls-srtp-cmake-option.patch @@ -0,0 +1,15 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6af16808..a12aa8cf 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -91,6 +91,10 @@ else() + message("SSL/TLS support is turned OFF") + endif() + ++if (USE_MBEDTLS_SSL_DTLS_SRTP) ++ add_definitions(-DHAVE_UPSTREAM_MBEDTLS_SRTP=1) ++endif() ++ + if (DEFINED DATASIZE ) + add_definitions(-DSHM_DATASIZE=${DATASIZE}) + endif() diff --git a/legacy/mistserver/fix-cmake-test-format.patch b/legacy/mistserver/fix-cmake-test-format.patch new file mode 100644 index 000000000..07161a2c5 --- /dev/null +++ b/legacy/mistserver/fix-cmake-test-format.patch @@ -0,0 +1,37 @@ +I don't know if this is correct. + +https://gitlab.kitware.com/cmake/cmake/-/issues/19109 + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -931,24 +931,24 @@ + ######################################## + add_executable(urltest test/url.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(urltest mist) +-add_test(URLTest COMMAND urltest) ++add_test(NAME URLTest COMMAND urltest) + add_executable(logtest test/log.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(logtest mist) +-add_test(LOGTest COMMAND logtest) ++add_test(NAME LOGTest COMMAND logtest) + add_executable(downloadertest test/downloader.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(downloadertest mist) +-add_test(DownloaderTest COMMAND downloadertest) ++add_test(NAME DownloaderTest COMMAND downloadertest) + add_executable(urireadertest test/urireader.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(urireadertest mist) +-add_test(URIReaderTest COMMAND urireadertest) ++add_test(NAME URIReaderTest COMMAND urireadertest) + add_executable(jsontest test/json.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(jsontest mist) +-add_test(JSONTest COMMAND jsontest) ++add_test(NAME JSONTest COMMAND jsontest) + add_executable(resolvetest test/resolve.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(resolvetest mist) + add_executable(bitwritertest test/bitwriter.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(bitwritertest mist) +-add_test(BitWriterTest COMMAND bitwritertest) ++add_test(NAME BitWriterTest COMMAND bitwritertest) + add_executable(streamstatustest test/status.cpp ${BINARY_DIR}/mist/.headers) + target_link_libraries(streamstatustest mist) + add_executable(websockettest test/websocket.cpp ${BINARY_DIR}/mist/.headers) diff --git a/legacy/mistserver/gizahnl-mbedtls-dev-from-origin-master.patch b/legacy/mistserver/gizahnl-mbedtls-dev-from-origin-master.patch new file mode 100644 index 000000000..29a6914e2 --- /dev/null +++ b/legacy/mistserver/gizahnl-mbedtls-dev-from-origin-master.patch @@ -0,0 +1,13180 @@ +From 0430a644dfcd0fcc0ea6494bdb8d431073b8361d Mon Sep 17 00:00:00 2001 +From: Matthew James <matt@Matthews-MacBook-Pro.local> +Date: Fri, 22 Jul 2022 00:44:28 +0800 +Subject: [PATCH 01/38] Enable Parameters on TSSRT listener + +--- + lib/socket_srt.cpp | 7 +++---- + lib/socket_srt.h | 2 +- + src/input/input_tssrt.cpp | 4 +++- + src/output/output_tssrt.cpp | 3 ++- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/lib/socket_srt.cpp b/lib/socket_srt.cpp +index a01117db..3e03bce4 100644 +--- a/lib/socket_srt.cpp ++++ b/lib/socket_srt.cpp +@@ -462,12 +462,11 @@ namespace Socket{ + + SRTServer::SRTServer(int fromSock){conn = SRTConnection(fromSock);} + +- SRTServer::SRTServer(int port, std::string hostname, bool nonblock, const std::string &_direction){ ++ SRTServer::SRTServer(int port, std::string hostname, std::map<std::string, std::string> _params, bool nonblock, const std::string &_direction){ + // We always create a server as listening +- std::map<std::string, std::string> listenMode; +- listenMode["mode"] = "listener"; ++ _params["mode"] = "listener"; + if (hostname == ""){hostname = "0.0.0.0";} +- conn.connect(hostname, port, _direction, listenMode); ++ conn.connect(hostname, port, _direction, _params); + conn.setBlocking(true); + if (!conn){ + ERROR_MSG("Unable to create socket"); +diff --git a/lib/socket_srt.h b/lib/socket_srt.h +index 5101d38d..07e947f8 100644 +--- a/lib/socket_srt.h ++++ b/lib/socket_srt.h +@@ -97,7 +97,7 @@ namespace Socket{ + public: + SRTServer(); + SRTServer(int existingSock); +- SRTServer(int port, std::string hostname, bool nonblock = false, const std::string &_direction = "input"); ++ SRTServer(int port, std::string hostname, std::map<std::string, std::string> params, bool nonblock = false, const std::string &_direction = "input"); + SRTConnection accept(bool nonblock = false, const std::string &direction = "input"); + void setBlocking(bool blocking); + bool connected() const; +diff --git a/src/input/input_tssrt.cpp b/src/input/input_tssrt.cpp +index 4a7adcef..d12f9cba 100644 +--- a/src/input/input_tssrt.cpp ++++ b/src/input/input_tssrt.cpp +@@ -137,7 +137,9 @@ namespace Mist{ + HTTP::URL u(source); + INFO_MSG("Parsed url: %s", u.getUrl().c_str()); + if (Socket::interpretSRTMode(u) == "listener"){ +- sSock = Socket::SRTServer(u.getPort(), u.host, false); ++ std::map<std::string, std::string> arguments; ++ HTTP::parseVars(u.args, arguments); ++ sSock = Socket::SRTServer(u.getPort(), u.host, arguments, false); + struct sigaction new_action; + struct sigaction cur_action; + new_action.sa_sigaction = signal_handler; +diff --git a/src/output/output_tssrt.cpp b/src/output/output_tssrt.cpp +index aa06189e..fb07b11e 100644 +--- a/src/output/output_tssrt.cpp ++++ b/src/output/output_tssrt.cpp +@@ -434,7 +434,8 @@ int main(int argc, char *argv[]){ + sigaction(SIGUSR1, &new_action, NULL); + } + if (conf.getInteger("port") && conf.getString("interface").size()){ +- server_socket = Socket::SRTServer(conf.getInteger("port"), conf.getString("interface"), false, "output"); ++ std::map<std::string, std::string> arguments; ++ server_socket = Socket::SRTServer(conf.getInteger("port"), conf.getString("interface"), arguments, false, "output"); + } + if (!server_socket.connected()){ + DEVEL_MSG("Failure to open socket"); +-- +2.25.1 + + +From 508506c241b2980d1aed607cd269ea60e5265e41 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Tue, 5 Jan 2021 15:14:04 +0100 +Subject: [PATCH 02/38] Fixes to UDP socket behaviour + +--- + lib/socket.cpp | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/lib/socket.cpp b/lib/socket.cpp +index 22f5e32b..865c3be7 100644 +--- a/lib/socket.cpp ++++ b/lib/socket.cpp +@@ -1713,15 +1713,19 @@ void Socket::UDPConnection::SetDestination(std::string destIp, uint32_t port){ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = family; + hints.ai_socktype = SOCK_DGRAM; +- hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED; ++ hints.ai_flags = AI_ADDRCONFIG | AI_ALL; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + int s = getaddrinfo(destIp.c_str(), ss.str().c_str(), &hints, &result); + if (s != 0){ +- FAIL_MSG("Could not connect UDP socket to %s:%i! Error: %s", destIp.c_str(), port, gai_strmagic(s)); +- return; ++ hints.ai_family = AF_UNSPEC; ++ s = getaddrinfo(destIp.c_str(), ss.str().c_str(), &hints, &result); ++ if (s != 0){ ++ FAIL_MSG("Could not connect UDP socket to %s:%i! Error: %s", destIp.c_str(), port, gai_strmagic(s)); ++ return; ++ } + } + + for (rp = result; rp != NULL; rp = rp->ai_next){ +@@ -1745,7 +1749,12 @@ void Socket::UDPConnection::SetDestination(std::string destIp, uint32_t port){ + bind(boundPort, boundAddr, boundMulti); + } + } +- HIGH_MSG("Set UDP destination: %s:%d (%s)", destIp.c_str(), port, addrFam(family)); ++ { ++ std::string trueDest; ++ uint32_t truePort; ++ GetDestination(trueDest, truePort); ++ HIGH_MSG("Set UDP destination: %s:%d => %s:%d (%s)", destIp.c_str(), port, trueDest.c_str(), truePort, addrFam(family)); ++ } + freeaddrinfo(result); + return; + //\todo Possibly detect and handle failure +@@ -1881,6 +1890,12 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str + for (rp = addr_result; rp != NULL; rp = rp->ai_next){ + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1){continue;} ++ if (rp->ai_family == AF_INET6){ ++ const int optval = 0; ++ if (setsockopt(sock, SOL_SOCKET, IPV6_V6ONLY, &optval, sizeof(optval)) < 0){ ++ WARN_MSG("Could not set IPv6 UDP socket to be dual-stack! %s", strerror(errno)); ++ } ++ } + checkRecvBuf(); + char human_addr[INET6_ADDRSTRLEN]; + char human_port[16]; +@@ -1909,7 +1924,7 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str + if (multicast){ + const int optval = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0){ +- WARN_MSG("Could not set multicast UDP socket re-use!"); ++ WARN_MSG("Could not set multicast UDP socket re-use! %s", strerror(errno)); + } + } + if (::bind(sock, rp->ai_addr, rp->ai_addrlen) == 0){ +-- +2.25.1 + + +From ed9910d587b5504d38e4f7ef2777f2ea7bd9b760 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Wed, 3 Aug 2022 14:58:05 +0200 +Subject: [PATCH 03/38] Fix for list limit in HLS/CMAF outputs when using + non-live + +--- + src/output/output_cmaf.cpp | 2 +- + src/output/output_hls.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/output/output_cmaf.cpp b/src/output/output_cmaf.cpp +index 756fceb8..4582a8b6 100644 +--- a/src/output/output_cmaf.cpp ++++ b/src/output/output_cmaf.cpp +@@ -284,7 +284,7 @@ namespace Mist{ + requestTid, + M.biggestFragment(timingTid) / 1000, + atol(H.GetVar("iMsn").c_str()), +- config->getInteger("listlimit"), ++ M.getLive()? config->getInteger("listlimit") : 0, + urlPrefix, + systemBoot, + bootMsOffset, +diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp +index 93410f54..19d083e6 100644 +--- a/src/output/output_hls.cpp ++++ b/src/output/output_hls.cpp +@@ -173,7 +173,7 @@ namespace Mist{ + requestTid, + M.biggestFragment(timingTid) / 1000, + atol(H.GetVar("iMsn").c_str()), +- config->getInteger("listlimit"), ++ M.getLive()? config->getInteger("listlimit") : 0, + urlPrefix, + systemBoot, + bootMsOffset, +-- +2.25.1 + + +From c37aac8898484903da8c2095d29125bf69888c0b Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 4 Aug 2022 09:14:51 +0200 +Subject: [PATCH 04/38] Remove "Rate=..." debug message from RTMP push output + +--- + src/output/output_rtmp.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp +index 69d5f91e..16a400d0 100644 +--- a/src/output/output_rtmp.cpp ++++ b/src/output/output_rtmp.cpp +@@ -618,7 +618,6 @@ namespace Mist{ + + if (type == "audio"){ + uint32_t rate = M.getRate(thisIdx); +- WARN_MSG("Rate=%i", rate); + rtmpheader[7] = 0x08; + if (codec == "AAC"){ + dataheader[0] += 0xA0; +-- +2.25.1 + + +From 4084768a3eb72026e901118e05fd17115dd785b3 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Tue, 5 Jul 2022 15:21:04 +0200 +Subject: [PATCH 05/38] Improved incoming push accept timing + +--- + src/output/output.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/output/output.cpp b/src/output/output.cpp +index 5c785bb0..1fa86eee 100644 +--- a/src/output/output.cpp ++++ b/src/output/output.cpp +@@ -2050,7 +2050,7 @@ namespace Mist{ + INFO_MSG("Waiting for stream reset before attempting push input accept (%" PRIu64 " <= %" PRIu64 "+500)", twoTime, oneTime); + while (streamStatus != STRMSTAT_OFF && keepGoing()){ + userSelect.clear(); +- Util::wait(1000); ++ Util::wait(250); + streamStatus = Util::getStreamStatus(streamName); + } + reconnect(); +@@ -2059,14 +2059,15 @@ namespace Mist{ + while (((streamStatus != STRMSTAT_WAIT && streamStatus != STRMSTAT_READY) || !meta) && keepGoing()){ + INFO_MSG("Waiting for %s buffer to be ready... (%u)", streamName.c_str(), streamStatus); + disconnect(); +- Util::wait(1000); + streamStatus = Util::getStreamStatus(streamName); + if (streamStatus == STRMSTAT_OFF || streamStatus == STRMSTAT_WAIT || streamStatus == STRMSTAT_READY){ + INFO_MSG("Reconnecting to %s buffer... (%u)", streamName.c_str(), streamStatus); +- Util::wait(500); + reconnect(); + streamStatus = Util::getStreamStatus(streamName); + } ++ if (((streamStatus != STRMSTAT_WAIT && streamStatus != STRMSTAT_READY) || !meta) && keepGoing()){ ++ Util::wait(100); ++ } + } + if (streamStatus == STRMSTAT_READY || streamStatus == STRMSTAT_WAIT){reconnect();} + if (!meta){ +-- +2.25.1 + + +From 14bc94ece51affb7cb6d52a491b97921ed420587 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Tue, 12 Jul 2022 15:47:29 +0200 +Subject: [PATCH 06/38] Prevent eternal sleep when waiting for RelAccX + structure to become ready + +--- + lib/util.cpp | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/lib/util.cpp b/lib/util.cpp +index d522a151..8dd75727 100644 +--- a/lib/util.cpp ++++ b/lib/util.cpp +@@ -446,7 +446,15 @@ namespace Util{ + hdrOffset = (uint16_t*)(p+26); + hdrEndPos = (uint64_t*)(p+28); + if (waitReady){ +- while (!isReady()){Util::sleep(50);} ++ uint64_t maxWait = Util::bootMS() + 10000; ++ while (!isReady()){ ++ if (Util::bootMS() > maxWait){ ++ FAIL_MSG("Waiting for RelAccX structure to be ready timed out, aborting"); ++ p = 0; ++ return; ++ } ++ Util::sleep(50); ++ } + } + if (isReady()){ + uint16_t offset = RAXHDR_FIELDOFFSET; +-- +2.25.1 + + +From 5bdd4a416e964ae0cfcc56d99c062691d1b3931d Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 14 Jul 2022 10:45:53 +0200 +Subject: [PATCH 07/38] Fix load balancer CPU usage + +--- + src/input/input_balancer.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/input/input_balancer.cpp b/src/input/input_balancer.cpp +index 448e6eff..36db5709 100644 +--- a/src/input/input_balancer.cpp ++++ b/src/input/input_balancer.cpp +@@ -140,6 +140,9 @@ namespace Mist{ + startTime = 0; // note success + break; // break out of while loop + } ++ }else{ ++ //Prevent 100% CPU usage if the response is slow ++ Util::sleep(25); + } + } + if (startTime){ +-- +2.25.1 + + +From fffe98804cb9c126ec91b7a7b67f2c917561ce02 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 30 Jun 2022 14:04:34 +0200 +Subject: [PATCH 08/38] Fixed TS SRT input not closing the connection when + stopping for internal reasons rather than external reasons + +--- + src/input/input_tssrt.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/input/input_tssrt.cpp b/src/input/input_tssrt.cpp +index d12f9cba..6cd614e7 100644 +--- a/src/input/input_tssrt.cpp ++++ b/src/input/input_tssrt.cpp +@@ -241,6 +241,7 @@ namespace Mist{ + } + // If we are here: we have a proper connection (either accepted or pull input) and should start parsing it as such + Input::streamMainLoop(); ++ srtConn.close(); + } + + bool inputTSSRT::needsLock(){return false;} +-- +2.25.1 + + +From 267a74f0f6d44b928b99312b356a3080579fdc1c Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 4 Aug 2022 16:43:04 +0200 +Subject: [PATCH 09/38] Fix track selector logic when multiple selections are + considered + +--- + lib/stream.cpp | 33 +++++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +diff --git a/lib/stream.cpp b/lib/stream.cpp +index 6036a8fd..715015d6 100644 +--- a/lib/stream.cpp ++++ b/lib/stream.cpp +@@ -1249,7 +1249,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + std::set<size_t> result; + + /*LTS-START*/ +- bool noSelAudio = false, noSelVideo = false, noSelSub = false; ++ bool noSelAudio = false, noSelVideo = false, noSelSub = false, noSelMeta = false; + // Then, select the tracks we've been asked to select. + if (targetParams.count("audio") && targetParams.at("audio").size()){ + if (targetParams.at("audio") != "-1" && targetParams.at("audio") != "none"){ +@@ -1270,6 +1270,11 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + result.insert(tracks.begin(), tracks.end()); + noSelSub = true; + } ++ if (targetParams.count("meta") && targetParams.at("meta").size()){ ++ std::set<size_t> tracks = Util::findTracks(M, capa, "meta", targetParams.at("meta"), UA); ++ result.insert(tracks.begin(), tracks.end()); ++ noSelMeta = true; ++ } + /*LTS-END*/ + + std::set<size_t> validTracks = M.getValidTracks(); +@@ -1291,6 +1296,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + // loop through all codec combinations, count max simultaneous active + unsigned int bestSoFar = 0; + unsigned int bestSoFarCount = 0; ++ unsigned int bestSoFarCountExtra = 0; + unsigned int index = 0; + bool allowBFrames = true; + if (capa.isMember("methods")){ +@@ -1319,6 +1325,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + if (problems){continue;} + if (noSelAudio && M.getType(*trit) == "audio"){continue;} + if (noSelVideo && M.getType(*trit) == "video"){continue;} ++ if (noSelMeta && M.getType(*trit) == "meta"){continue;} + if (noSelSub && (M.getType(*trit) == "subtitle" || M.getCodec(*trit) == "subtitle")){continue;} + result.insert(*trit); + } +@@ -1328,6 +1335,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + + jsonForEachConst(capa["codecs"], it){ + unsigned int selCounter = 0; ++ unsigned int extraCounter = 0; + if ((*it).size() > 0){ + jsonForEachConst((*it), itb){ + if ((*itb).size() > 0){ +@@ -1360,6 +1368,26 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + } + if (problems){break;} + selCounter++; ++ extraCounter++; ++ if (!multiSel){break;} ++ } ++ } ++ for (std::set<size_t>::iterator itd = validTracks.begin(); itd != validTracks.end(); itd++){ ++ if ((!byType && M.getCodec(*itd) == strRef.substr(shift)) || ++ (byType && M.getType(*itd) == strRef.substr(shift)) || strRef.substr(shift) == "*"){ ++ // user-agent-check ++ bool problems = false; ++ if (capa.isMember("exceptions") && capa["exceptions"].isObject() && ++ capa["exceptions"].size()){ ++ jsonForEachConst(capa["exceptions"], ex){ ++ if (ex.key() == "codec:" + strRef.substr(shift)){ ++ problems = !Util::checkException(*ex, UA); ++ break; ++ } ++ } ++ } ++ if (problems){break;} ++ extraCounter++; + if (!multiSel){break;} + } + } +@@ -1367,8 +1395,9 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri + } + } + if (selCounter == result.size()){ +- if (selCounter > bestSoFarCount){ ++ if (selCounter > bestSoFarCount || (selCounter == bestSoFarCount && extraCounter > bestSoFarCountExtra)){ + bestSoFarCount = selCounter; ++ bestSoFarCountExtra = extraCounter; + bestSoFar = index; + HIGH_MSG("Matched %u: %s", selCounter, (*it).toString().c_str()); + } +-- +2.25.1 + + +From 3734c90544a68d03a1a69438f00f215c517fec01 Mon Sep 17 00:00:00 2001 +From: Phencys <phencys@phencys.com> +Date: Sun, 20 Sep 2020 20:31:17 +0200 +Subject: [PATCH 10/38] Added support for raw passthrough of MPEG2-TS data + +--- + src/input/input_ts.cpp | 73 ++++++++++++++++++++++++++++++++--- + src/input/input_ts.h | 5 +++ + src/input/input_tsrist.cpp | 54 +++++++++++++++++++++++++- + src/input/input_tsrist.h | 6 +++ + src/input/input_tssrt.cpp | 35 +++++++++++++++++ + src/input/input_tssrt.h | 4 ++ + src/io.cpp | 7 ++++ + src/io.h | 1 + + src/output/output_httpts.cpp | 1 + + src/output/output_ts.cpp | 1 + + src/output/output_ts_base.cpp | 5 +++ + src/output/output_tsrist.cpp | 1 + + src/output/output_tssrt.cpp | 1 + + 13 files changed, 187 insertions(+), 7 deletions(-) + +diff --git a/src/input/input_ts.cpp b/src/input/input_ts.cpp +index 98300411..cfe3f7cd 100644 +--- a/src/input/input_ts.cpp ++++ b/src/input/input_ts.cpp +@@ -134,6 +134,13 @@ void parseThread(void *mistIn){ + } + } + } ++ ++ //On shutdown, make sure to clean up stream buffer ++ if (idx != INVALID_TRACK_ID){ ++ tthread::lock_guard<tthread::mutex> guard(threadClaimMutex); ++ input->liveFinalize(idx); ++ } ++ + std::string reason = "unknown reason"; + if (!(Util::bootSecs() - threadTimer[tid] < THREAD_TIMEOUT)){reason = "thread timeout";} + if (!cfgPointer->is_active){reason = "input shutting down";} +@@ -155,6 +162,9 @@ namespace Mist{ + /// Constructor of TS Input + /// \arg cfg Util::Config that contains all current configurations. + inputTS::inputTS(Util::Config *cfg) : Input(cfg){ ++ rawMode = false; ++ rawIdx = INVALID_TRACK_ID; ++ lastRawPacket = 0; + capa["name"] = "TS"; + capa["desc"] = + "This input allows you to stream MPEG2-TS data from static files (/*.ts), streamed files " +@@ -188,6 +198,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("AC3"); + capa["codecs"][0u][1u].append("MP2"); + capa["codecs"][0u][1u].append("opus"); ++ capa["codecs"][1u][0u].append("rawts"); + inFile = NULL; + inputProcess = 0; + isFinished = false; +@@ -232,6 +243,16 @@ namespace Mist{ + "Alternative stream to load for playback when there is no active broadcast"; + capa["optional"]["fallback_stream"]["type"] = "str"; + capa["optional"]["fallback_stream"]["default"] = ""; ++ ++ capa["optional"]["raw"]["name"] = "Raw input mode"; ++ capa["optional"]["raw"]["help"] = "Enable raw MPEG-TS passthrough mode"; ++ capa["optional"]["raw"]["option"] = "--raw"; ++ ++ JSON::Value option; ++ option["long"] = "raw"; ++ option["short"] = "R"; ++ option["help"] = "Enable raw MPEG-TS passthrough mode"; ++ config->addOption("raw", option); + } + + inputTS::~inputTS(){ +@@ -257,6 +278,10 @@ namespace Mist{ + /// Live Setup of TS Input + bool inputTS::preRun(){ + INFO_MSG("Prerun: %s", config->getString("input").c_str()); ++ ++ rawMode = config->getBool("raw"); ++ if (rawMode){INFO_MSG("Entering raw mode");} ++ + // streamed standard input + if (config->getString("input") == "-"){ + standAlone = false; +@@ -520,9 +545,28 @@ namespace Mist{ + } + if (tcpCon.Received().available(188) && tcpCon.Received().get()[0] == 0x47){ + std::string newData = tcpCon.Received().remove(188); +- tsBuf.FromPointer(newData.data()); +- liveStream.add(tsBuf); +- if (!liveStream.isDataTrack(tsBuf.getPID())){liveStream.parse(tsBuf.getPID());} ++ if (rawMode){ ++ keepAlive(); ++ rawBuffer.append(newData); ++ if (rawBuffer.size() >= 1316 && (lastRawPacket == 0 || lastRawPacket != Util::bootMS())){ ++ if (rawIdx == INVALID_TRACK_ID){ ++ rawIdx = meta.addTrack(); ++ meta.setType(rawIdx, "meta"); ++ meta.setCodec(rawIdx, "rawts"); ++ meta.setID(rawIdx, 1); ++ userSelect[rawIdx].reload(streamName, rawIdx, COMM_STATUS_SOURCE); ++ } ++ uint64_t packetTime = Util::bootMS(); ++ thisPacket.genericFill(packetTime, 0, 1, rawBuffer, rawBuffer.size(), 0, 0); ++ bufferLivePacket(thisPacket); ++ lastRawPacket = packetTime; ++ rawBuffer.truncate(0); ++ } ++ }else { ++ tsBuf.FromPointer(newData.data()); ++ liveStream.add(tsBuf); ++ if (!liveStream.isDataTrack(tsBuf.getPID())){liveStream.parse(tsBuf.getPID());} ++ } + } + } + noDataSince = Util::bootSecs(); +@@ -543,7 +587,26 @@ namespace Mist{ + gettingData = true; + INFO_MSG("Now receiving UDP data..."); + } +- assembler.assemble(liveStream, udpCon.data, udpCon.data.size()); ++ if (rawMode){ ++ keepAlive(); ++ rawBuffer.append(udpCon.data, udpCon.data.size()); ++ if (rawBuffer.size() >= 1316 && (lastRawPacket == 0 || lastRawPacket != Util::bootMS())){ ++ if (rawIdx == INVALID_TRACK_ID){ ++ rawIdx = meta.addTrack(); ++ meta.setType(rawIdx, "meta"); ++ meta.setCodec(rawIdx, "rawts"); ++ meta.setID(rawIdx, 1); ++ userSelect[rawIdx].reload(streamName, rawIdx, COMM_STATUS_SOURCE); ++ } ++ uint64_t packetTime = Util::bootMS(); ++ thisPacket.genericFill(packetTime, 0, 1, rawBuffer, rawBuffer.size(), 0, 0); ++ bufferLivePacket(thisPacket); ++ lastRawPacket = packetTime; ++ rawBuffer.truncate(0); ++ } ++ }else{ ++ assembler.assemble(liveStream, udpCon.data, udpCon.data.size()); ++ } + } + if (!received){ + Util::sleep(100); +@@ -578,7 +641,7 @@ namespace Mist{ + } + + std::set<size_t> activeTracks = liveStream.getActiveTracks(); +- { ++ if (!rawMode){ + tthread::lock_guard<tthread::mutex> guard(threadClaimMutex); + if (hasStarted && !threadTimer.size()){ + if (!isAlwaysOn()){ +diff --git a/src/input/input_ts.h b/src/input/input_ts.h +index e810ddb4..3116725d 100644 +--- a/src/input/input_ts.h ++++ b/src/input/input_ts.h +@@ -41,6 +41,11 @@ namespace Mist{ + pid_t inputProcess; + size_t tmpIdx; + bool isFinished; ++ ++ bool rawMode; ++ Util::ResizeablePointer rawBuffer; ++ size_t rawIdx; ++ uint64_t lastRawPacket; + }; + }// namespace Mist + +diff --git a/src/input/input_tsrist.cpp b/src/input/input_tsrist.cpp +index 18b05c9d..5b95aa9f 100644 +--- a/src/input/input_tsrist.cpp ++++ b/src/input/input_tsrist.cpp +@@ -66,6 +66,10 @@ namespace Mist{ + /// Constructor of TS Input + /// \arg cfg Util::Config that contains all current configurations. + inputTSRIST::inputTSRIST(Util::Config *cfg) : Input(cfg){ ++ rawMode = false; ++ rawIdx = INVALID_TRACK_ID; ++ lastRawPacket = 0; ++ hasRaw = false; + connPtr = this; + cnfPtr = config; + +@@ -96,6 +100,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("AC3"); + capa["codecs"][0u][1u].append("MP2"); + capa["codecs"][0u][1u].append("opus"); ++ capa["codecs"][1u][0u].append("rawts"); + + JSON::Value option; + option["arg"] = "integer"; +@@ -132,6 +137,15 @@ namespace Mist{ + capa["optional"]["profile"]["type"] = "select"; + capa["optional"]["profile"]["option"] = "--profile"; + ++ capa["optional"]["raw"]["name"] = "Raw input mode"; ++ capa["optional"]["raw"]["help"] = "Enable raw MPEG-TS passthrough mode"; ++ capa["optional"]["raw"]["option"] = "--raw"; ++ ++ option["long"] = "raw"; ++ option["short"] = "R"; ++ option["help"] = "Enable raw MPEG-TS passthrough mode"; ++ config->addOption("raw", option); ++ + lastTimeStamp = 0; + timeStampOffset = 0; + receiver_ctx = 0; +@@ -146,6 +160,9 @@ namespace Mist{ + + /// Live Setup of SRT Input. Runs only if we are the "main" thread + bool inputTSRIST::preRun(){ ++ rawMode = config->getBool("raw"); ++ if (rawMode){INFO_MSG("Entering raw mode");} ++ + std::string source = config->getString("input"); + standAlone = false; + HTTP::URL u(source); +@@ -161,6 +178,20 @@ namespace Mist{ + // Retrieve the next packet to be played from the srt connection. + void inputTSRIST::getNext(size_t idx){ + thisPacket.null(); ++ if (rawMode){ ++ //Set to false so the other thread knows its safe to fill ++ hasRaw = false; ++ while (!hasRaw && config->is_active){ ++ Util::sleep(50); ++ if (!bufferActive()){ ++ Util::logExitReason("Buffer shut down"); ++ return; ++ } ++ } ++ //if hasRaw, thisPacket has been filled by the other thread ++ return; ++ } ++ + while (!thisPacket && config->is_active){ + if (tsStream.hasPacket()){ + tsStream.getEarliestPacket(thisPacket); +@@ -228,8 +259,27 @@ namespace Mist{ + } + + void inputTSRIST::addData(const char * ptr, size_t len){ +- for (size_t o = 0; o <= len-188; o += 188){ +- tsStream.parse((char*)ptr+o, 0); ++ for (size_t o = 0; o+188 <= len; o += 188){ ++ if (rawMode){ ++ rawBuffer.append(ptr+o, 188); ++ if (!hasRaw && rawBuffer.size() >= 1316 && (lastRawPacket == 0 || lastRawPacket != Util::bootMS())){ ++ if (rawIdx == INVALID_TRACK_ID){ ++ rawIdx = meta.addTrack(); ++ meta.setType(rawIdx, "meta"); ++ meta.setCodec(rawIdx, "rawts"); ++ meta.setID(rawIdx, 1); ++ userSelect[rawIdx].reload(streamName, rawIdx, COMM_STATUS_SOURCE); ++ } ++ thisTime = Util::bootMS(); ++ thisIdx = rawIdx; ++ thisPacket.genericFill(thisTime, 0, 1, rawBuffer, rawBuffer.size(), 0, 0); ++ lastRawPacket = thisTime; ++ rawBuffer.truncate(0); ++ hasRaw = true; ++ } ++ }else{ ++ tsStream.parse((char*)ptr+o, 0); ++ } + } + } + +diff --git a/src/input/input_tsrist.h b/src/input/input_tsrist.h +index 3bc29e1c..731f9b04 100644 +--- a/src/input/input_tsrist.h ++++ b/src/input/input_tsrist.h +@@ -33,6 +33,12 @@ namespace Mist{ + virtual void connStats(Comms::Statistics &statComm); + + struct rist_ctx *receiver_ctx; ++ ++ bool rawMode; ++ Util::ResizeablePointer rawBuffer; ++ size_t rawIdx; ++ uint64_t lastRawPacket; ++ bool hasRaw; + }; + }// namespace Mist + +diff --git a/src/input/input_tssrt.cpp b/src/input/input_tssrt.cpp +index 6cd614e7..da69be29 100644 +--- a/src/input/input_tssrt.cpp ++++ b/src/input/input_tssrt.cpp +@@ -25,6 +25,7 @@ + Util::Config *cfgPointer = NULL; + std::string baseStreamName; + Socket::SRTServer sSock; ++bool rawMode = false; + + void (*oldSignal)(int, siginfo_t *,void *) = 0; + +@@ -49,6 +50,8 @@ namespace Mist{ + /// Constructor of TS Input + /// \arg cfg Util::Config that contains all current configurations. + inputTSSRT::inputTSSRT(Util::Config *cfg, SRTSOCKET s) : Input(cfg){ ++ rawIdx = INVALID_TRACK_ID; ++ lastRawPacket = 0; + capa["name"] = "TSSRT"; + capa["desc"] = "This input allows for processing MPEG2-TS-based SRT streams. Use mode=listener " + "for push input."; +@@ -66,6 +69,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("AC3"); + capa["codecs"][0u][1u].append("MP2"); + capa["codecs"][0u][1u].append("opus"); ++ capa["codecs"][1u][0u].append("rawts"); + + JSON::Value option; + option["arg"] = "integer"; +@@ -103,7 +107,16 @@ namespace Mist{ + capa["optional"]["acceptable"]["select"][2u][0u] = 2; + capa["optional"]["acceptable"]["select"][2u][1u] = "Disallow non-matching streamid"; + ++ capa["optional"]["raw"]["name"] = "Raw input mode"; ++ capa["optional"]["raw"]["help"] = "Enable raw MPEG-TS passthrough mode"; ++ capa["optional"]["raw"]["option"] = "--raw"; + ++ option.null(); ++ option["long"] = "raw"; ++ option["short"] = "R"; ++ option["help"] = "Enable raw MPEG-TS passthrough mode"; ++ config->addOption("raw", option); ++ + // Setup if we are called form with a thread for push-based input. + if (s != -1){ + srtConn = Socket::SRTConnection(s); +@@ -131,6 +144,8 @@ namespace Mist{ + + /// Live Setup of SRT Input. Runs only if we are the "main" thread + bool inputTSSRT::preRun(){ ++ rawMode = config->getBool("raw"); ++ if (rawMode){INFO_MSG("Entering raw mode");} + if (srtConn.getSocket() == -1){ + std::string source = config->getString("input"); + standAlone = false; +@@ -183,6 +198,26 @@ namespace Mist{ + + size_t recvSize = srtConn.RecvNow(); + if (recvSize){ ++ if (rawMode){ ++ keepAlive(); ++ rawBuffer.append(srtConn.recvbuf, recvSize); ++ if (rawBuffer.size() >= 1316 && (lastRawPacket == 0 || lastRawPacket != Util::bootMS())){ ++ if (rawIdx == INVALID_TRACK_ID){ ++ rawIdx = meta.addTrack(); ++ meta.setType(rawIdx, "meta"); ++ meta.setCodec(rawIdx, "rawts"); ++ meta.setID(rawIdx, 1); ++ userSelect[rawIdx].reload(streamName, rawIdx, COMM_STATUS_SOURCE); ++ } ++ uint64_t packetTime = Util::bootMS(); ++ thisPacket.genericFill(packetTime, 0, 1, rawBuffer, rawBuffer.size(), 0, 0); ++ bufferLivePacket(thisPacket); ++ lastRawPacket = packetTime; ++ rawBuffer.truncate(0); ++ return; ++ } ++ continue; ++ } + if (assembler.assemble(tsStream, srtConn.recvbuf, recvSize, true)){hasPacket = tsStream.hasPacket();} + }else if (srtConn){ + // This should not happen as the SRT socket is read blocking and won't return until there is +diff --git a/src/input/input_tssrt.h b/src/input/input_tssrt.h +index 40fa05c1..4f337b48 100644 +--- a/src/input/input_tssrt.h ++++ b/src/input/input_tssrt.h +@@ -41,6 +41,10 @@ namespace Mist{ + Socket::SRTConnection srtConn; + bool singularFlag; + virtual void connStats(Comms::Statistics &statComm); ++ ++ Util::ResizeablePointer rawBuffer; ++ size_t rawIdx; ++ uint64_t lastRawPacket; + }; + }// namespace Mist + +diff --git a/src/io.cpp b/src/io.cpp +index 6a5844c4..fea32193 100644 +--- a/src/io.cpp ++++ b/src/io.cpp +@@ -292,6 +292,13 @@ namespace Mist{ + tPages.setInt("avail", pageOffset + packDataLen, pageIdx); + } + ++ /// Wraps up the buffering of a shared memory data page ++ /// \param idx The track index of the page to finalize ++ void InOutBase::liveFinalize(size_t idx){ ++ if (!livePage.count(idx)){return;} ++ bufferFinalize(idx, livePage[idx]); ++ } ++ + /// Wraps up the buffering of a shared memory data page + /// \param idx The track index of the page to finalize + void InOutBase::bufferFinalize(size_t idx, IPC::sharedPage & page){ +diff --git a/src/io.h b/src/io.h +index d839952a..e6545929 100644 +--- a/src/io.h ++++ b/src/io.h +@@ -21,6 +21,7 @@ namespace Mist{ + + bool bufferStart(size_t idx, uint32_t pageNumber, IPC::sharedPage & page, DTSC::Meta & aMeta); + void bufferFinalize(size_t idx, IPC::sharedPage & page); ++ void liveFinalize(size_t idx); + bool isCurrentLivePage(size_t idx, uint32_t pageNumber); + void bufferRemove(size_t idx, uint32_t pageNumber); + void bufferLivePacket(const DTSC::Packet &packet); +diff --git a/src/output/output_httpts.cpp b/src/output/output_httpts.cpp +index 6aab2b9b..9daa9dc3 100644 +--- a/src/output/output_httpts.cpp ++++ b/src/output/output_httpts.cpp +@@ -135,6 +135,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("+AC3"); + capa["codecs"][0u][1u].append("+MP2"); + capa["codecs"][0u][1u].append("+opus"); ++ capa["codecs"][1u][0u].append("rawts"); + capa["methods"][0u]["handler"] = "http"; + capa["methods"][0u]["type"] = "html5/video/mpeg"; + capa["methods"][0u]["hrn"] = "TS HTTP progressive"; +diff --git a/src/output/output_ts.cpp b/src/output/output_ts.cpp +index d2addc24..561bf9aa 100644 +--- a/src/output/output_ts.cpp ++++ b/src/output/output_ts.cpp +@@ -179,6 +179,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("+AC3"); + capa["codecs"][0u][1u].append("+MP2"); + capa["codecs"][0u][1u].append("+opus"); ++ capa["codecs"][1u][0u].append("rawts"); + cfg->addConnectorOptions(8888, capa); + config = cfg; + capa["push_urls"].append("tsudp://*"); +diff --git a/src/output/output_ts_base.cpp b/src/output/output_ts_base.cpp +index 17b2a8ce..c4163e7f 100644 +--- a/src/output/output_ts_base.cpp ++++ b/src/output/output_ts_base.cpp +@@ -75,6 +75,11 @@ namespace Mist{ + size_t dataLen = 0; + thisPacket.getString("data", dataPointer, dataLen); // data + ++ if (codec == "rawts"){ ++ for (size_t i = 0; i+188 <= dataLen; i+=188){sendTS(dataPointer+i, 188);} ++ return; ++ } ++ + packTime *= 90; + std::string bs; + // prepare bufferstring +diff --git a/src/output/output_tsrist.cpp b/src/output/output_tsrist.cpp +index ee57d8ee..c4e03f80 100644 +--- a/src/output/output_tsrist.cpp ++++ b/src/output/output_tsrist.cpp +@@ -202,6 +202,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("+AC3"); + capa["codecs"][0u][1u].append("+MP2"); + capa["codecs"][0u][1u].append("+opus"); ++ capa["codecs"][1u][0u].append("rawts"); + + capa["optional"]["profile"]["name"] = "RIST profile"; + capa["optional"]["profile"]["help"] = "RIST profile to use"; +diff --git a/src/output/output_tssrt.cpp b/src/output/output_tssrt.cpp +index fb07b11e..db07dc91 100644 +--- a/src/output/output_tssrt.cpp ++++ b/src/output/output_tssrt.cpp +@@ -200,6 +200,7 @@ namespace Mist{ + capa["codecs"][0u][1u].append("AC3"); + capa["codecs"][0u][1u].append("MP2"); + capa["codecs"][0u][1u].append("opus"); ++ capa["codecs"][1u][0u].append("rawts"); + cfg->addConnectorOptions(8889, capa); + config = cfg; + capa["push_urls"].append("srt://*"); +-- +2.25.1 + + +From 6c117b63cfe85a204b48dfddddb355f416b39364 Mon Sep 17 00:00:00 2001 +From: Alex Kordic <alexandarkordic@gmail.com> +Date: Thu, 4 Aug 2022 14:49:57 +0200 +Subject: [PATCH 11/38] Add s3 protocol to `URIReader` + +--- + lib/timing.cpp | 12 +++++ + lib/timing.h | 1 + + lib/urireader.cpp | 114 +++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 125 insertions(+), 2 deletions(-) + +diff --git a/lib/timing.cpp b/lib/timing.cpp +index 036f0b29..f339f4fe 100644 +--- a/lib/timing.cpp ++++ b/lib/timing.cpp +@@ -114,3 +114,15 @@ std::string Util::getUTCString(uint64_t epoch){ + ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); + return std::string(result); + } ++ ++std::string Util::getDateString(uint64_t epoch){ ++ char buffer[80]; ++ time_t rawtime = epoch; ++ if (!epoch) { ++ time(&rawtime); ++ } ++ struct tm * timeinfo; ++ timeinfo = localtime(&rawtime); ++ strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S %z", timeinfo); ++ return std::string(buffer); ++} +diff --git a/lib/timing.h b/lib/timing.h +index 107ccee5..b2a4d612 100644 +--- a/lib/timing.h ++++ b/lib/timing.h +@@ -17,4 +17,5 @@ namespace Util{ + uint64_t getNTP(); + uint64_t epoch(); ///< Gets the amount of seconds since 01/01/1970. + std::string getUTCString(uint64_t epoch = 0); ++ std::string getDateString(uint64_t epoch = 0); + }// namespace Util +diff --git a/lib/urireader.cpp b/lib/urireader.cpp +index 80f204c8..ad85b052 100644 +--- a/lib/urireader.cpp ++++ b/lib/urireader.cpp +@@ -3,11 +3,86 @@ + #include "timing.h" + #include "urireader.h" + #include "util.h" ++#include "encode.h" + #include <sys/mman.h> + #include <sys/stat.h> ++#include <cstdlib> ++#include <ctime> + + namespace HTTP{ + ++ // When another protocol needs this, rename struct to HeaderOverride or similar ++ struct HTTPHeadThenGet { ++ bool continueOperation; ++ std::string date, headAuthorization, getAuthorization; ++ ++ HTTPHeadThenGet() : continueOperation(false) {} ++ ++ void prepareHeadHeaders(HTTP::Downloader& downloader) { ++ if(!continueOperation) return; ++ downloader.setHeader("Date", date); ++ downloader.setHeader("Authorization", headAuthorization); ++ } ++ ++ void prepareGetHeaders(HTTP::Downloader& downloader) { ++ if(!continueOperation) return; ++ // .setHeader() overwrites existing header value ++ downloader.setHeader("Date", date); ++ downloader.setHeader("Authorization", getAuthorization); ++ } ++ }; ++ ++#ifndef NOSSL ++ inline bool s3CalculateSignature(std::string& signature, const std::string method, const std::string date, const std::string& requestPath, const std::string& accessKey, const std::string& secret) { ++ std::string toSign = method + "\n\n\n" + date + "\n" + requestPath; ++ unsigned char signatureBytes[MBEDTLS_MD_MAX_SIZE]; ++ const int sha1Size = 20; ++ mbedtls_md_context_t md_ctx = {0}; ++ // TODO: When we use MBEDTLS_MD_SHA512 ? Consult documentation/code ++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); ++ if (!md_info){ FAIL_MSG("error s3 MBEDTLS_MD_SHA1 unavailable"); return false; } ++ int status = mbedtls_md_setup(&md_ctx, md_info, 1); ++ if(status != 0) { FAIL_MSG("error s3 mbedtls_md_setup error %d", status); return false; } ++ status = mbedtls_md_hmac_starts(&md_ctx, (const unsigned char *)secret.c_str(), secret.size()); ++ if(status != 0) { FAIL_MSG("error s3 mbedtls_md_hmac_starts error %d", status); return false; } ++ status = mbedtls_md_hmac_update(&md_ctx, (const unsigned char *)toSign.c_str(), toSign.size()); ++ if(status != 0) { FAIL_MSG("error s3 mbedtls_md_hmac_update error %d", status); return false; } ++ status = mbedtls_md_hmac_finish(&md_ctx, signatureBytes); ++ if(status != 0) { FAIL_MSG("error s3 mbedtls_md_hmac_finish error %d", status); return false; } ++ std::string base64encoded = Encodings::Base64::encode(std::string((const char*)signatureBytes, sha1Size)); ++ signature = "AWS " + accessKey + ":" + base64encoded; ++ return true; ++ } ++ // Input url == s3+https://s3_key:secret@storage.googleapis.com/alexk-dms-upload-test/testvideo.ts ++ // Transform to: ++ // url=https://storage.googleapis.com/alexk-dms-upload-test/testvideo.ts ++ // header Date: ${Util::getDateString(()} ++ // header Authorization: AWS ${url.user}:${signature} ++ inline HTTPHeadThenGet s3TransformToHttp(HTTP::URL& url) { ++ HTTPHeadThenGet result; ++ result.date = Util::getDateString(); ++ // remove "s3+" prefix ++ url.protocol = url.protocol.erase(0, 3); ++ // Use user and pass to create signature and remove from HTTP request ++ std::string accessKey(url.user), secret(url.pass); ++ url.user = ""; ++ url.pass = ""; ++ std::string requestPath = "/" + Encodings::URL::encode(url.path, "/:=@[]#?&"); ++ if(url.args.size()) requestPath += "?" + url.args; ++ // Calculate Authorization data ++ if(!s3CalculateSignature(result.headAuthorization, "HEAD", result.date, requestPath, accessKey, secret)) { ++ result.continueOperation = false; ++ return result; ++ } ++ if(!s3CalculateSignature(result.getAuthorization, "GET", result.date, requestPath, accessKey, secret)) { ++ result.continueOperation = false; ++ return result; ++ } ++ result.continueOperation = true; ++ return result; ++ } ++#endif // ifndef NOSSL ++ + void URIReader::init(){ + handle = -1; + mapped = 0; +@@ -97,12 +172,45 @@ namespace HTTP{ + } + } + ++ // prepare for s3 and http ++ HTTPHeadThenGet httpHeaderOverride; ++ ++#ifndef NOSSL ++ // In case of s3 URI we prepare HTTP request with AWS authorization and rely on HTTP logic below ++ if (myURI.protocol == "s3+https" || myURI.protocol == "s3+http"){ ++ // Check fallback to global credentials in env vars ++ bool haveCredentials = myURI.user.size() && myURI.pass.size(); ++ if(!haveCredentials) { ++ // Use environment variables ++ char * envValue = std::getenv("S3_ACCESS_KEY_ID"); ++ if(envValue == NULL) { ++ FAIL_MSG("error s3 uri without credentials. Consider setting S3_ACCESS_KEY_ID env var"); ++ return false; ++ } ++ myURI.user = envValue; ++ envValue = std::getenv("S3_SECRET_ACCESS_KEY"); ++ if(envValue == NULL) { ++ FAIL_MSG("error s3 uri without credentials. Consider setting S3_SECRET_ACCESS_KEY env var"); ++ return false; ++ } ++ myURI.pass = envValue; ++ } ++ // Transform s3 url to HTTP request: ++ httpHeaderOverride = s3TransformToHttp(myURI); ++ bool errorInSignatureCalculation = !httpHeaderOverride.continueOperation; ++ if(errorInSignatureCalculation) return false; ++ // Do not return, continue to HTTP case ++ } ++#endif // ifndef NOSSL ++ + // HTTP, stream or regular download? + if (myURI.protocol == "http" || myURI.protocol == "https"){ +- stateType = HTTP::HTTP; ++ stateType = HTTP; ++ downer.clearHeaders(); + ++ // One set of headers specified for HEAD request ++ httpHeaderOverride.prepareHeadHeaders(downer); + // Send HEAD request to determine range request is supported, and get total length +- downer.clearHeaders(); + if (userAgentOverride.size()){downer.setHeader("User-Agent", userAgentOverride);} + if (!downer.head(myURI) || !downer.isOk()){ + FAIL_MSG("Error getting URI info for '%s': %" PRIu32 " %s", myURI.getUrl().c_str(), +@@ -120,6 +228,8 @@ namespace HTTP{ + myURI = downer.lastURL(); + } + ++ // Other set of headers specified for GET request ++ httpHeaderOverride.prepareGetHeaders(downer); + // streaming mode when size is unknown + if (!supportRangeRequest){ + MEDIUM_MSG("URI get without range request: %s, totalsize: %zu", myURI.getUrl().c_str(), totalSize); +-- +2.25.1 + + +From df4076a06eeb6fbc0fc20d9ace0091eb476420a2 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Wed, 17 Aug 2022 14:57:29 +0200 +Subject: [PATCH 12/38] Added ResizeablePointer::shift operator to shift data + forward in buffer + +--- + lib/util.cpp | 11 +++++++++++ + lib/util.h | 1 + + 2 files changed, 12 insertions(+) + +diff --git a/lib/util.cpp b/lib/util.cpp +index 8dd75727..d4ff380f 100644 +--- a/lib/util.cpp ++++ b/lib/util.cpp +@@ -191,6 +191,17 @@ namespace Util{ + maxSize = 0; + } + ++ void ResizeablePointer::shift(size_t byteCount){ ++ //Shifting the entire buffer is easy, we do nothing and set size to zero ++ if (byteCount >= currSize){ ++ currSize = 0; ++ return; ++ } ++ //Shifting partial needs a memmove and size change ++ memmove(ptr, ((char*)ptr)+byteCount, currSize-byteCount); ++ currSize -= byteCount; ++ } ++ + bool ResizeablePointer::assign(const void *p, uint32_t l){ + if (!allocate(l)){return false;} + memcpy(ptr, p, l); +diff --git a/lib/util.h b/lib/util.h +index 84b0d56c..d28a7f76 100644 +--- a/lib/util.h ++++ b/lib/util.h +@@ -45,6 +45,7 @@ namespace Util{ + bool append(const void *p, uint32_t l); + bool append(const std::string &str); + bool allocate(uint32_t l); ++ void shift(size_t byteCount); + uint32_t rsize(); + void truncate(const size_t newLen); + inline operator char *(){return (char *)ptr;} +-- +2.25.1 + + +From 44c28097332b0a137c4674bcfd8d243b593b3cee Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 18 Aug 2022 02:44:11 +0200 +Subject: [PATCH 13/38] Decreased verbosity of harmless data offset warnings, + increased verbosity of harmful ones + +--- + src/input/input.cpp | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/src/input/input.cpp b/src/input/input.cpp +index 942a55f8..0a062392 100644 +--- a/src/input/input.cpp ++++ b/src/input/input.cpp +@@ -1382,10 +1382,12 @@ namespace Mist{ + size_t currPos = tPages.getInt("avail", pageIdx); + if (currPos){ + size_t keySize = keys.getSize(keyNum); +- if (currPos-prevPos != keySize){ +- INFO_MSG("Key %" PRIu32 " was %zu bytes but should've been %zu bytes! (differs %d)", keyNum, currPos-prevPos, keySize, (int)(currPos-prevPos-keySize)); +- }else{ ++ if (currPos-prevPos == keySize){ + VERYHIGH_MSG("Key %" PRIu32 " was %zu bytes", keyNum, currPos-prevPos); ++ }else if (currPos-prevPos > keySize){ ++ FAIL_MSG("Key %" PRIu32 " was %zu bytes but should've been %zu bytes! (differs %d)", keyNum, currPos-prevPos, keySize, (int)(currPos-prevPos-keySize)); ++ }else{ ++ MEDIUM_MSG("Key %" PRIu32 " was %zu bytes but should've been %zu bytes! (differs %d)", keyNum, currPos-prevPos, keySize, (int)(currPos-prevPos-keySize)); + } + ++keyNum; + prevPos = currPos; +@@ -1412,8 +1414,12 @@ namespace Mist{ + size_t currPos = tPages.getInt("avail", pageIdx); + if (currPos){ + size_t keySize = keys.getSize(keyNum); +- if (currPos-prevPos != keySize){ +- INFO_MSG("Key %" PRIu32 " was %zu bytes but should've been %zu bytes! (differs %d)", keyNum, currPos-prevPos, keySize, (int)(currPos-prevPos-keySize)); ++ if (currPos-prevPos == keySize){ ++ VERYHIGH_MSG("Key %" PRIu32 " was %zu bytes", keyNum, currPos-prevPos); ++ }else if (currPos-prevPos > keySize){ ++ FAIL_MSG("Key %" PRIu32 " was %zu bytes but should've been %zu bytes! (differs %d)", keyNum, currPos-prevPos, keySize, (int)(currPos-prevPos-keySize)); ++ }else{ ++ MEDIUM_MSG("Key %" PRIu32 " was %zu bytes but should've been %zu bytes! (differs %d)", keyNum, currPos-prevPos, keySize, (int)(currPos-prevPos-keySize)); + } + ++keyNum; + prevPos = currPos; +-- +2.25.1 + + +From 747438746c068f9217f804fab4d58bdf57156a43 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 18 Aug 2022 15:45:46 +0200 +Subject: [PATCH 14/38] Change VoD data page logic to use wallclock seconds + rather than loop iterations for timeouts + +--- + src/input/input.cpp | 30 ++++++++++++++++++++++-------- + src/input/input.h | 2 +- + 2 files changed, 23 insertions(+), 9 deletions(-) + +diff --git a/src/input/input.cpp b/src/input/input.cpp +index 0a062392..a86fe3cd 100644 +--- a/src/input/input.cpp ++++ b/src/input/input.cpp +@@ -1022,28 +1022,42 @@ namespace Mist{ + } + + void Input::removeUnused(){ ++ uint64_t cTime = Util::bootSecs(); + std::set<size_t> validTracks = M.getValidTracks(); ++ std::map<size_t, std::set<uint32_t> > checkedPages; + for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); ++it){ + Util::RelAccX &tPages = meta.pages(*it); + for (size_t i = tPages.getDeleted(); i < tPages.getEndPos(); i++){ + uint64_t pageNum = tPages.getInt("firstkey", i); ++ checkedPages[*it].insert(pageNum); + if (pageCounter[*it].count(pageNum)){ + // If the page is still being written to, reset the counter rather than potentially unloading it + if (isCurrentLivePage(*it, pageNum)){ +- pageCounter[*it][pageNum] = DEFAULT_PAGE_TIMEOUT; ++ pageCounter[*it][pageNum] = cTime; + continue; + } +- --pageCounter[*it][pageNum]; +- if (!pageCounter[*it][pageNum]){ ++ if (cTime > pageCounter[*it][pageNum] + DEFAULT_PAGE_TIMEOUT){ + pageCounter[*it].erase(pageNum); + bufferRemove(*it, pageNum); + } ++ }else{ ++ pageCounter[*it][pageNum] = cTime; + } +- else{ +- pageCounter[*it][pageNum] = DEFAULT_PAGE_TIMEOUT; ++ } ++ } ++ //Check pages we buffered but forgot about ++ for (std::map<size_t, std::map<uint32_t, size_t> >::iterator it = pageCounter.begin(); ++ it != pageCounter.end(); it++){ ++ for (std::map<uint32_t, size_t>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++){ ++ if (!checkedPages.count(it->first) || !checkedPages[it->first].count(it2->first)){ ++ INFO_MSG("Deleting forgotten page %zu:%" PRIu32, it->first, it2->first); ++ bufferRemove(it->first, it2->first); ++ it->second.erase(it2); ++ it2 = it->second.begin(); + } + } + } ++ + } + + std::string formatGUID(const std::string &val){ +@@ -1290,8 +1304,8 @@ namespace Mist{ + } + uint32_t pageNumber = tPages.getInt("firstkey", pageIdx); + if (isBuffered(idx, pageNumber, meta)){ +- // Mark the page for removal after 15 seconds of no one watching it +- pageCounter[idx][pageNumber] = DEFAULT_PAGE_TIMEOUT; ++ // Mark the page as still actively requested ++ pageCounter[idx][pageNumber] = Util::bootSecs(); + DONTEVEN_MSG("Track %zu, key %" PRIu32 " is already buffered in page %" PRIu32 + ". Cancelling bufferFrame", + idx, keyNum, pageNumber); +@@ -1432,7 +1446,7 @@ namespace Mist{ + idx, pageNumber, tPages.getInt("firsttime", pageIdx), thisTime, bufferTimer); + INFO_MSG(" (%" PRIu32 "/%" PRIu64 " parts, %" PRIu64 " bytes)", packCounter, + tPages.getInt("parts", pageIdx), byteCounter); +- pageCounter[idx][pageNumber] = DEFAULT_PAGE_TIMEOUT; ++ pageCounter[idx][pageNumber] = Util::bootSecs(); + return true; + } + +diff --git a/src/input/input.h b/src/input/input.h +index 28880337..8d7e8891 100644 +--- a/src/input/input.h ++++ b/src/input/input.h +@@ -87,7 +87,7 @@ namespace Mist{ + + IPC::sharedPage streamStatus; + +- std::map<size_t, std::map<uint32_t, size_t> > pageCounter; ++ std::map<size_t, std::map<uint32_t, uint64_t> > pageCounter; + + static Input *singleton; + +-- +2.25.1 + + +From b210b4f5afc98b3cb4ea46e607267e12cf868831 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Wed, 17 Aug 2022 17:06:25 +0200 +Subject: [PATCH 15/38] Fixed seek-related bugs in URIReader for HTTP sources + +--- + lib/urireader.cpp | 40 ++++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 18 deletions(-) + +diff --git a/lib/urireader.cpp b/lib/urireader.cpp +index ad85b052..d4dd0e31 100644 +--- a/lib/urireader.cpp ++++ b/lib/urireader.cpp +@@ -255,20 +255,30 @@ namespace HTTP{ + + // seek to pos, return true if succeeded. + bool URIReader::seek(const uint64_t pos){ +- if (isSeekable()){ +- allData.truncate(0); +- bufPos = 0; +- if (stateType == HTTP::File){ +- curPos = pos; +- return true; +- }else if (stateType == HTTP::HTTP && supportRangeRequest){ +- INFO_MSG("SEEK: RangeRequest to %" PRIu64, pos); +- if (!downer.getRangeNonBlocking(myURI.getUrl(), pos, 0)){ +- FAIL_MSG("error loading request"); +- } +- } ++ //Seeking in a non-seekable source? No-op, always fails. ++ if (!isSeekable()){return false;} ++ ++ //Reset internal buffers ++ allData.truncate(0); ++ bufPos = 0; ++ ++ //Files always succeed because we use memmap ++ if (stateType == HTTP::File){ ++ curPos = pos; ++ return true; + } + ++ //HTTP-based needs to do a range request ++ if (stateType == HTTP::HTTP && supportRangeRequest){ ++ downer.getSocket().close(); ++ downer.getSocket().Received().clear(); ++ if (!downer.getRangeNonBlocking(myURI.getUrl(), pos, 0)){ ++ FAIL_MSG("Error making range request"); ++ return false; ++ } ++ curPos = pos; ++ return true; ++ } + return false; + } + +@@ -323,19 +333,13 @@ namespace HTTP{ + + }else if (stateType == HTTP::HTTP){ + downer.continueNonBlocking(cb); +- if (curPos == downer.const_data().size()){ +- Util::sleep(50); +- } +- curPos = downer.const_data().size(); + }else{// streaming mode + int s; +- static int totaal = 0; + if ((downer.getSocket() && downer.getSocket().spool())){// || downer.getSocket().Received().size() > 0){ + s = downer.getSocket().Received().bytes(wantedLen); + std::string buf = downer.getSocket().Received().remove(s); + + cb.dataCallback(buf.data(), s); +- totaal += s; + }else{ + Util::sleep(50); + } +-- +2.25.1 + + +From 01a2ff54edb0cb544495bff57d8cc2a61440db2a Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Wed, 17 Aug 2022 14:57:48 +0200 +Subject: [PATCH 16/38] Converted MP4 input to use URIReader + +--- + src/input/input_mp4.cpp | 518 ++++++++++++++++++++++------------------ + src/input/input_mp4.h | 15 +- + 2 files changed, 298 insertions(+), 235 deletions(-) + +diff --git a/src/input/input_mp4.cpp b/src/input/input_mp4.cpp +index 2e1c7923..f85911fb 100644 +--- a/src/input/input_mp4.cpp ++++ b/src/input/input_mp4.cpp +@@ -159,11 +159,14 @@ namespace Mist{ + } + + inputMP4::inputMP4(Util::Config *cfg) : Input(cfg){ +- malSize = 4; // initialise data read buffer to 0; +- data = (char *)malloc(malSize); + capa["name"] = "MP4"; + capa["desc"] = "This input allows streaming of MP4 files as Video on Demand."; +- capa["source_match"] = "/*.mp4"; ++ capa["source_match"].append("/*.mp4"); ++ capa["source_match"].append("http://*.mp4"); ++ capa["source_match"].append("https://*.mp4"); ++ capa["source_match"].append("s3+http://*.mp4"); ++ capa["source_match"].append("s3+https://*.mp4"); ++ capa["source_match"].append("mp4:*"); + capa["source_file"] = "$source"; + capa["priority"] = 9; + capa["codecs"][0u][0u].append("HEVC"); +@@ -173,10 +176,9 @@ namespace Mist{ + capa["codecs"][0u][1u].append("AAC"); + capa["codecs"][0u][1u].append("AC3"); + capa["codecs"][0u][1u].append("MP3"); ++ readPos = 0; + } + +- inputMP4::~inputMP4(){free(data);} +- + bool inputMP4::checkArguments(){ + if (config->getString("input") == "-"){ + std::cerr << "Input from stdin not yet supported" << std::endl; +@@ -199,255 +201,292 @@ namespace Mist{ + + bool inputMP4::preRun(){ + // open File +- inFile = fopen(config->getString("input").c_str(), "r"); ++ std::string inUrl = config->getString("input"); ++ if (inUrl.size() > 4 && inUrl.substr(0, 4) == "mp4:"){inUrl.erase(0, 4);} ++ inFile.open(inUrl); + if (!inFile){return false;} ++ if (!inFile.isSeekable()){ ++ FAIL_MSG("MP4 input only supports seekable data sources, for now, and this source is not seekable: %s", config->getString("input").c_str()); ++ return false; ++ } + return true; + } + ++ void inputMP4::dataCallback(const char *ptr, size_t size){readBuffer.append(ptr, size);} ++ + bool inputMP4::readHeader(){ + if (!inFile){ + INFO_MSG("inFile failed!"); + return false; + } ++ bool hasMoov = false; ++ readBuffer.truncate(0); ++ readPos = 0; + + // first we get the necessary header parts + size_t tNumber = 0; +- while (!feof(inFile)){ +- std::string boxType = MP4::readBoxType(inFile); +- if (boxType == "erro"){break;} ++ activityCounter = Util::bootSecs(); ++ while (inFile && keepRunning()){ ++ //Read box header if needed ++ while (readBuffer.size() < 16 && inFile && keepRunning()){inFile.readSome(16, *this);} ++ //Failed? Abort. ++ if (readBuffer.size() < 16){ ++ FAIL_MSG("Could not read box header from input!"); ++ break; ++ } ++ //Box type is always on bytes 5-8 from the start of a box ++ std::string boxType = std::string(readBuffer+4, 4); ++ uint64_t boxSize = MP4::calcBoxSize(readBuffer); + if (boxType == "moov"){ +- MP4::MOOV moovBox; +- moovBox.read(inFile); +- // for all box in moov ++ while (readBuffer.size() < boxSize && inFile && keepRunning()){inFile.readSome(boxSize-readBuffer.size(), *this);} ++ if (readBuffer.size() < boxSize){ ++ FAIL_MSG("Could not read entire MOOV box into memory"); ++ break; ++ } ++ MP4::Box moovBox(readBuffer, false); + +- std::deque<MP4::TRAK> trak = moovBox.getChildren<MP4::TRAK>(); ++ // for all box in moov ++ std::deque<MP4::TRAK> trak = ((MP4::MOOV*)&moovBox)->getChildren<MP4::TRAK>(); + for (std::deque<MP4::TRAK>::iterator trakIt = trak.begin(); trakIt != trak.end(); trakIt++){ + trackHeaders.push_back(mp4TrackHeader()); + trackHeaders.rbegin()->read(*trakIt); + } +- continue; ++ hasMoov = true; ++ break; + } +- if (!MP4::skipBox(inFile)){// moving on to next box +- FAIL_MSG("Error in skipping box, exiting"); +- return false; ++ activityCounter = Util::bootSecs(); ++ //Skip to next box ++ if (readBuffer.size() > boxSize){ ++ readBuffer.shift(boxSize); ++ readPos += boxSize; ++ }else{ ++ readBuffer.truncate(0); ++ if (!inFile.seek(readPos + boxSize)){ ++ FAIL_MSG("Seek to %" PRIu64 " failed! Aborting load", readPos+boxSize); ++ } ++ readPos = inFile.getPos(); + } + } +- fseeko(inFile, 0, SEEK_SET); + + // See whether a separate header file exists. +- if (readExistingHeader()){return true;} +- HIGH_MSG("Not read existing header"); ++ if (readExistingHeader()){ ++ bps = 0; ++ std::set<size_t> tracks = M.getValidTracks(); ++ for (std::set<size_t>::iterator it = tracks.begin(); it != tracks.end(); it++){bps += M.getBps(*it);} ++ return true; ++ } ++ INFO_MSG("Not read existing header"); + + meta.reInit(isSingular() ? streamName : ""); ++ if (!hasMoov){ ++ FAIL_MSG("No MOOV box found; aborting header creation!"); ++ return false; ++ } + + tNumber = 0; + // Create header file from MP4 data +- while (!feof(inFile)){ +- std::string boxType = MP4::readBoxType(inFile); +- if (boxType == "erro"){break;} +- if (boxType == "moov"){ +- MP4::MOOV moovBox; +- moovBox.read(inFile); ++ MP4::Box moovBox(readBuffer, false); + +- std::deque<MP4::TRAK> trak = moovBox.getChildren<MP4::TRAK>(); +- HIGH_MSG("Obtained %zu trak Boxes", trak.size()); ++ std::deque<MP4::TRAK> trak = ((MP4::MOOV*)&moovBox)->getChildren<MP4::TRAK>(); ++ HIGH_MSG("Obtained %zu trak Boxes", trak.size()); + +- for (std::deque<MP4::TRAK>::iterator trakIt = trak.begin(); trakIt != trak.end(); trakIt++){ +- MP4::MDIA mdiaBox = trakIt->getChild<MP4::MDIA>(); ++ for (std::deque<MP4::TRAK>::iterator trakIt = trak.begin(); trakIt != trak.end(); trakIt++){ ++ MP4::MDIA mdiaBox = trakIt->getChild<MP4::MDIA>(); + +- std::string hdlrType = mdiaBox.getChild<MP4::HDLR>().getHandlerType(); +- if (hdlrType != "vide" && hdlrType != "soun" && hdlrType != "sbtl"){ +- INFO_MSG("Unsupported handler: %s", hdlrType.c_str()); +- continue; +- } ++ std::string hdlrType = mdiaBox.getChild<MP4::HDLR>().getHandlerType(); ++ if (hdlrType != "vide" && hdlrType != "soun" && hdlrType != "sbtl"){ ++ INFO_MSG("Unsupported handler: %s", hdlrType.c_str()); ++ continue; ++ } + +- tNumber = meta.addTrack(); ++ tNumber = meta.addTrack(); + +- MP4::TKHD tkhdBox = trakIt->getChild<MP4::TKHD>(); +- if (tkhdBox.getWidth() > 0){ +- meta.setWidth(tNumber, tkhdBox.getWidth()); +- meta.setHeight(tNumber, tkhdBox.getHeight()); +- } +- meta.setID(tNumber, tkhdBox.getTrackID()); +- +- MP4::MDHD mdhdBox = mdiaBox.getChild<MP4::MDHD>(); +- uint64_t timescale = mdhdBox.getTimeScale(); +- meta.setLang(tNumber, mdhdBox.getLanguage()); +- +- MP4::STBL stblBox = mdiaBox.getChild<MP4::MINF>().getChild<MP4::STBL>(); +- +- MP4::STSD stsdBox = stblBox.getChild<MP4::STSD>(); +- MP4::Box sEntryBox = stsdBox.getEntry(0); +- std::string sType = sEntryBox.getType(); +- HIGH_MSG("Found track %zu of type %s", tNumber, sType.c_str()); +- +- if (sType == "avc1" || sType == "h264" || sType == "mp4v"){ +- MP4::VisualSampleEntry &vEntryBox = (MP4::VisualSampleEntry &)sEntryBox; +- meta.setType(tNumber, "video"); +- meta.setCodec(tNumber, "H264"); +- if (!meta.getWidth(tNumber)){ +- meta.setWidth(tNumber, vEntryBox.getWidth()); +- meta.setHeight(tNumber, vEntryBox.getHeight()); +- } +- MP4::Box initBox = vEntryBox.getCLAP(); +- if (initBox.isType("avcC")){ +- meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); +- } +- initBox = vEntryBox.getPASP(); +- if (initBox.isType("avcC")){ +- meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); +- } +- /// this is a hacky way around invalid FLV data (since it gets ignored nearly +- /// everywhere, but we do need correct data... +- if (!meta.getWidth(tNumber)){ +- h264::sequenceParameterSet sps; +- sps.fromDTSCInit(meta.getInit(tNumber)); +- h264::SPSMeta spsChar = sps.getCharacteristics(); +- meta.setWidth(tNumber, spsChar.width); +- meta.setHeight(tNumber, spsChar.height); +- } +- } +- if (sType == "hev1" || sType == "hvc1"){ +- MP4::VisualSampleEntry &vEntryBox = (MP4::VisualSampleEntry &)sEntryBox; +- meta.setType(tNumber, "video"); +- meta.setCodec(tNumber, "HEVC"); +- if (!meta.getWidth(tNumber)){ +- meta.setWidth(tNumber, vEntryBox.getWidth()); +- meta.setHeight(tNumber, vEntryBox.getHeight()); +- } +- MP4::Box initBox = vEntryBox.getCLAP(); +- if (initBox.isType("hvcC")){ +- meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); +- } +- initBox = vEntryBox.getPASP(); +- if (initBox.isType("hvcC")){ +- meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); +- } +- } +- if (sType == "mp4a" || sType == "aac " || sType == "ac-3"){ +- MP4::AudioSampleEntry &aEntryBox = (MP4::AudioSampleEntry &)sEntryBox; +- meta.setType(tNumber, "audio"); +- meta.setChannels(tNumber, aEntryBox.getChannelCount()); +- meta.setRate(tNumber, aEntryBox.getSampleRate()); +- +- if (sType == "ac-3"){ +- meta.setCodec(tNumber, "AC3"); +- }else{ +- MP4::ESDS esdsBox = (MP4::ESDS &)(aEntryBox.getCodecBox()); +- meta.setCodec(tNumber, esdsBox.getCodec()); +- meta.setInit(tNumber, esdsBox.getInitData()); +- } +- meta.setSize(tNumber, 16); ///\todo this might be nice to calculate from mp4 file; +- } +- if (sType == "tx3g"){// plain text subtitles +- meta.setType(tNumber, "meta"); +- meta.setCodec(tNumber, "subtitle"); ++ MP4::TKHD tkhdBox = trakIt->getChild<MP4::TKHD>(); ++ if (tkhdBox.getWidth() > 0){ ++ meta.setWidth(tNumber, tkhdBox.getWidth()); ++ meta.setHeight(tNumber, tkhdBox.getHeight()); ++ } ++ meta.setID(tNumber, tkhdBox.getTrackID()); ++ ++ MP4::MDHD mdhdBox = mdiaBox.getChild<MP4::MDHD>(); ++ uint64_t timescale = mdhdBox.getTimeScale(); ++ meta.setLang(tNumber, mdhdBox.getLanguage()); ++ ++ MP4::STBL stblBox = mdiaBox.getChild<MP4::MINF>().getChild<MP4::STBL>(); ++ ++ MP4::STSD stsdBox = stblBox.getChild<MP4::STSD>(); ++ MP4::Box sEntryBox = stsdBox.getEntry(0); ++ std::string sType = sEntryBox.getType(); ++ HIGH_MSG("Found track %zu of type %s", tNumber, sType.c_str()); ++ ++ if (sType == "avc1" || sType == "h264" || sType == "mp4v"){ ++ MP4::VisualSampleEntry &vEntryBox = (MP4::VisualSampleEntry &)sEntryBox; ++ meta.setType(tNumber, "video"); ++ meta.setCodec(tNumber, "H264"); ++ if (!meta.getWidth(tNumber)){ ++ meta.setWidth(tNumber, vEntryBox.getWidth()); ++ meta.setHeight(tNumber, vEntryBox.getHeight()); ++ } ++ MP4::Box initBox = vEntryBox.getCLAP(); ++ if (initBox.isType("avcC")){ ++ meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); ++ } ++ initBox = vEntryBox.getPASP(); ++ if (initBox.isType("avcC")){ ++ meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); ++ } ++ /// this is a hacky way around invalid FLV data (since it gets ignored nearly ++ /// everywhere, but we do need correct data... ++ if (!meta.getWidth(tNumber)){ ++ h264::sequenceParameterSet sps; ++ sps.fromDTSCInit(meta.getInit(tNumber)); ++ h264::SPSMeta spsChar = sps.getCharacteristics(); ++ meta.setWidth(tNumber, spsChar.width); ++ meta.setHeight(tNumber, spsChar.height); ++ } ++ } ++ if (sType == "hev1" || sType == "hvc1"){ ++ MP4::VisualSampleEntry &vEntryBox = (MP4::VisualSampleEntry &)sEntryBox; ++ meta.setType(tNumber, "video"); ++ meta.setCodec(tNumber, "HEVC"); ++ if (!meta.getWidth(tNumber)){ ++ meta.setWidth(tNumber, vEntryBox.getWidth()); ++ meta.setHeight(tNumber, vEntryBox.getHeight()); ++ } ++ MP4::Box initBox = vEntryBox.getCLAP(); ++ if (initBox.isType("hvcC")){ ++ meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); ++ } ++ initBox = vEntryBox.getPASP(); ++ if (initBox.isType("hvcC")){ ++ meta.setInit(tNumber, initBox.payload(), initBox.payloadSize()); ++ } ++ } ++ if (sType == "mp4a" || sType == "aac " || sType == "ac-3"){ ++ MP4::AudioSampleEntry &aEntryBox = (MP4::AudioSampleEntry &)sEntryBox; ++ meta.setType(tNumber, "audio"); ++ meta.setChannels(tNumber, aEntryBox.getChannelCount()); ++ meta.setRate(tNumber, aEntryBox.getSampleRate()); ++ ++ if (sType == "ac-3"){ ++ meta.setCodec(tNumber, "AC3"); ++ }else{ ++ MP4::ESDS esdsBox = (MP4::ESDS &)(aEntryBox.getCodecBox()); ++ meta.setCodec(tNumber, esdsBox.getCodec()); ++ meta.setInit(tNumber, esdsBox.getInitData()); ++ } ++ meta.setSize(tNumber, 16); ///\todo this might be nice to calculate from mp4 file; ++ } ++ if (sType == "tx3g"){// plain text subtitles ++ meta.setType(tNumber, "meta"); ++ meta.setCodec(tNumber, "subtitle"); ++ } ++ ++ MP4::STSS stssBox = stblBox.getChild<MP4::STSS>(); ++ MP4::STTS sttsBox = stblBox.getChild<MP4::STTS>(); ++ MP4::STSZ stszBox = stblBox.getChild<MP4::STSZ>(); ++ MP4::STCO stcoBox = stblBox.getChild<MP4::STCO>(); ++ MP4::CO64 co64Box = stblBox.getChild<MP4::CO64>(); ++ MP4::STSC stscBox = stblBox.getChild<MP4::STSC>(); ++ MP4::CTTS cttsBox = stblBox.getChild<MP4::CTTS>(); // optional ctts box ++ ++ bool stco64 = co64Box.isType("co64"); ++ bool hasCTTS = cttsBox.isType("ctts"); ++ ++ uint64_t totaldur = 0; ///\todo note: set this to begin time ++ mp4PartBpos BsetPart; ++ ++ uint64_t entryNo = 0; ++ uint64_t sampleNo = 0; ++ ++ uint64_t stssIndex = 0; ++ uint64_t stcoIndex = 0; ++ uint64_t stscIndex = 0; ++ uint64_t cttsIndex = 0; // current ctts Index we are reading ++ uint64_t cttsEntryRead = 0; // current part of ctts we are reading ++ ++ uint64_t stssCount = stssBox.getEntryCount(); ++ uint64_t stscCount = stscBox.getEntryCount(); ++ uint64_t stszCount = stszBox.getSampleCount(); ++ uint64_t stcoCount = (stco64 ? co64Box.getEntryCount() : stcoBox.getEntryCount()); ++ ++ MP4::STTSEntry sttsEntry = sttsBox.getSTTSEntry(0); ++ ++ uint32_t fromSTCOinSTSC = 0; ++ uint64_t tmpOffset = (stco64 ? co64Box.getChunkOffset(0) : stcoBox.getChunkOffset(0)); ++ ++ uint64_t nextFirstChunk = (stscCount > 1 ? stscBox.getSTSCEntry(1).firstChunk - 1 : stcoCount); ++ ++ for (uint64_t stszIndex = 0; stszIndex < stszCount; ++stszIndex){ ++ if (stcoIndex >= nextFirstChunk){ ++ ++stscIndex; ++ nextFirstChunk = ++ (stscIndex + 1 < stscCount ? stscBox.getSTSCEntry(stscIndex + 1).firstChunk - 1 : stcoCount); ++ } ++ BsetPart.keyframe = (meta.getType(tNumber) == "video" && stssIndex < stssCount && ++ stszIndex + 1 == stssBox.getSampleNumber(stssIndex)); ++ if (BsetPart.keyframe){++stssIndex;} ++ // in bpos set ++ BsetPart.stcoNr = stcoIndex; ++ // bpos = chunkoffset[samplenr] in stco ++ BsetPart.bpos = tmpOffset; ++ ++fromSTCOinSTSC; ++ if (fromSTCOinSTSC < stscBox.getSTSCEntry(stscIndex).samplesPerChunk){// as long as we are still in this chunk ++ tmpOffset += stszBox.getEntrySize(stszIndex); ++ }else{ ++ ++stcoIndex; ++ fromSTCOinSTSC = 0; ++ tmpOffset = (stco64 ? co64Box.getChunkOffset(stcoIndex) : stcoBox.getChunkOffset(stcoIndex)); ++ } ++ BsetPart.time = (totaldur * 1000) / timescale; ++ totaldur += sttsEntry.sampleDelta; ++ sampleNo++; ++ if (sampleNo >= sttsEntry.sampleCount){ ++ ++entryNo; ++ sampleNo = 0; ++ if (entryNo < sttsBox.getEntryCount()){sttsEntry = sttsBox.getSTTSEntry(entryNo);} ++ } ++ ++ if (hasCTTS){ ++ MP4::CTTSEntry cttsEntry = cttsBox.getCTTSEntry(cttsIndex); ++ cttsEntryRead++; ++ if (cttsEntryRead >= cttsEntry.sampleCount){ ++ ++cttsIndex; ++ cttsEntryRead = 0; + } ++ BsetPart.timeOffset = (cttsEntry.sampleOffset * 1000) / timescale; ++ }else{ ++ BsetPart.timeOffset = 0; ++ } + +- MP4::STSS stssBox = stblBox.getChild<MP4::STSS>(); +- MP4::STTS sttsBox = stblBox.getChild<MP4::STTS>(); +- MP4::STSZ stszBox = stblBox.getChild<MP4::STSZ>(); +- MP4::STCO stcoBox = stblBox.getChild<MP4::STCO>(); +- MP4::CO64 co64Box = stblBox.getChild<MP4::CO64>(); +- MP4::STSC stscBox = stblBox.getChild<MP4::STSC>(); +- MP4::CTTS cttsBox = stblBox.getChild<MP4::CTTS>(); // optional ctts box +- +- bool stco64 = co64Box.isType("co64"); +- bool hasCTTS = cttsBox.isType("ctts"); +- +- uint64_t totaldur = 0; ///\todo note: set this to begin time +- mp4PartBpos BsetPart; +- +- uint64_t entryNo = 0; +- uint64_t sampleNo = 0; +- +- uint64_t stssIndex = 0; +- uint64_t stcoIndex = 0; +- uint64_t stscIndex = 0; +- uint64_t cttsIndex = 0; // current ctts Index we are reading +- uint64_t cttsEntryRead = 0; // current part of ctts we are reading +- +- uint64_t stssCount = stssBox.getEntryCount(); +- uint64_t stscCount = stscBox.getEntryCount(); +- uint64_t stszCount = stszBox.getSampleCount(); +- uint64_t stcoCount = (stco64 ? co64Box.getEntryCount() : stcoBox.getEntryCount()); +- +- MP4::STTSEntry sttsEntry = sttsBox.getSTTSEntry(0); +- +- uint32_t fromSTCOinSTSC = 0; +- uint64_t tmpOffset = (stco64 ? co64Box.getChunkOffset(0) : stcoBox.getChunkOffset(0)); +- +- uint64_t nextFirstChunk = (stscCount > 1 ? stscBox.getSTSCEntry(1).firstChunk - 1 : stcoCount); +- +- for (uint64_t stszIndex = 0; stszIndex < stszCount; ++stszIndex){ +- if (stcoIndex >= nextFirstChunk){ +- ++stscIndex; +- nextFirstChunk = +- (stscIndex + 1 < stscCount ? stscBox.getSTSCEntry(stscIndex + 1).firstChunk - 1 : stcoCount); +- } +- BsetPart.keyframe = (meta.getType(tNumber) == "video" && stssIndex < stssCount && +- stszIndex + 1 == stssBox.getSampleNumber(stssIndex)); +- if (BsetPart.keyframe){++stssIndex;} +- // in bpos set +- BsetPart.stcoNr = stcoIndex; +- // bpos = chunkoffset[samplenr] in stco +- BsetPart.bpos = tmpOffset; +- ++fromSTCOinSTSC; +- if (fromSTCOinSTSC < stscBox.getSTSCEntry(stscIndex).samplesPerChunk){// as long as we are still in this chunk +- tmpOffset += stszBox.getEntrySize(stszIndex); +- }else{ +- ++stcoIndex; +- fromSTCOinSTSC = 0; +- tmpOffset = (stco64 ? co64Box.getChunkOffset(stcoIndex) : stcoBox.getChunkOffset(stcoIndex)); +- } +- BsetPart.time = (totaldur * 1000) / timescale; +- totaldur += sttsEntry.sampleDelta; +- sampleNo++; +- if (sampleNo >= sttsEntry.sampleCount){ +- ++entryNo; +- sampleNo = 0; +- if (entryNo < sttsBox.getEntryCount()){sttsEntry = sttsBox.getSTTSEntry(entryNo);} +- } +- +- if (hasCTTS){ +- MP4::CTTSEntry cttsEntry = cttsBox.getCTTSEntry(cttsIndex); +- cttsEntryRead++; +- if (cttsEntryRead >= cttsEntry.sampleCount){ +- ++cttsIndex; +- cttsEntryRead = 0; +- } +- BsetPart.timeOffset = (cttsEntry.sampleOffset * 1000) / timescale; +- }else{ +- BsetPart.timeOffset = 0; +- } +- +- if (sType == "tx3g"){ +- if (stszBox.getEntrySize(stszIndex) <= 2 && false){ +- FAIL_MSG("size <=2"); +- }else{ +- long long packSendSize = 0; +- packSendSize = 24 + (BsetPart.timeOffset ? 17 : 0) + (BsetPart.bpos ? 15 : 0) + 19 + +- stszBox.getEntrySize(stszIndex) + 11 - 2 + 19; +- meta.update(BsetPart.time, BsetPart.timeOffset, tNumber, +- stszBox.getEntrySize(stszIndex) - 2, BsetPart.bpos, true, packSendSize); +- } +- }else{ +- meta.update(BsetPart.time, BsetPart.timeOffset, tNumber, +- stszBox.getEntrySize(stszIndex), BsetPart.bpos, BsetPart.keyframe); +- } ++ if (sType == "tx3g"){ ++ if (stszBox.getEntrySize(stszIndex) <= 2 && false){ ++ FAIL_MSG("size <=2"); ++ }else{ ++ long long packSendSize = 0; ++ packSendSize = 24 + (BsetPart.timeOffset ? 17 : 0) + (BsetPart.bpos ? 15 : 0) + 19 + ++ stszBox.getEntrySize(stszIndex) + 11 - 2 + 19; ++ meta.update(BsetPart.time, BsetPart.timeOffset, tNumber, ++ stszBox.getEntrySize(stszIndex) - 2, BsetPart.bpos, true, packSendSize); + } ++ }else{ ++ meta.update(BsetPart.time, BsetPart.timeOffset, tNumber, ++ stszBox.getEntrySize(stszIndex), BsetPart.bpos, BsetPart.keyframe); + } +- continue; +- } +- if (!MP4::skipBox(inFile)){// moving on to next box +- FAIL_MSG("Error in Skipping box, exiting"); +- return false; + } + } +- clearerr(inFile); + + // outputting dtsh file +- M.toFile(config->getString("input") + ".dtsh"); ++ std::string inUrl = config->getString("input"); ++ if (inUrl.size() > 4 && inUrl.substr(0, 4) == "mp4:"){inUrl.erase(0, 4);} ++ if (inUrl != "-" && HTTP::URL(inUrl).isLocalPath()){ ++ M.toFile(inUrl + ".dtsh"); ++ }else{ ++ INFO_MSG("Skipping header write, as the source is not a local file"); ++ } ++ bps = 0; ++ std::set<size_t> tracks = M.getValidTracks(); ++ for (std::set<size_t>::iterator it = tracks.begin(); it != tracks.end(); it++){bps += M.getBps(*it);} + return true; + } + +@@ -474,23 +513,48 @@ namespace Mist{ + ++nextKeyNum; + } + } +- if (fseeko(inFile, curPart.bpos, SEEK_SET)){ +- FAIL_MSG("seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno)); +- thisPacket.null(); +- return; ++ if (curPart.bpos < readPos || curPart.bpos > readPos + readBuffer.size() + 512*1024 + bps){ ++ INFO_MSG("Buffer contains %" PRIu64 "-%" PRIu64 ", but we need %" PRIu64 "; seeking!", readPos, readPos + readBuffer.size(), curPart.bpos); ++ readBuffer.truncate(0); ++ if (!inFile.seek(curPart.bpos)){ ++ FAIL_MSG("seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno)); ++ thisPacket.null(); ++ return; ++ } ++ readPos = inFile.getPos(); ++ }else{ ++ //If we have more than 5MiB buffered and are more than 5MiB into the buffer, shift the first 4MiB off the buffer. ++ //This prevents infinite growth of the read buffer for large files ++ if (readBuffer.size() >= 5*1024*1024 && curPart.bpos > readPos + 5*1024*1024 + bps){ ++ readBuffer.shift(4*1024*1024); ++ readPos += 4*1024*1024; ++ } + } +- if (curPart.size > malSize){ +- data = (char *)realloc(data, curPart.size); +- malSize = curPart.size; ++ ++ while (readPos+readBuffer.size() < curPart.bpos+curPart.size && inFile && keepRunning()){ ++ inFile.readSome((curPart.bpos+curPart.size) - (readPos+readBuffer.size()), *this); + } +- if (fread(data, curPart.size, 1, inFile) != 1){ +- FAIL_MSG("read unsuccessful at %ld", ftell(inFile)); +- thisPacket.null(); +- return; ++ if (readPos+readBuffer.size() < curPart.bpos+curPart.size){ ++ FAIL_MSG("Read unsuccessful at %" PRIu64 ", seeking to retry...", readPos+readBuffer.size()); ++ readBuffer.truncate(0); ++ if (!inFile.seek(curPart.bpos)){ ++ FAIL_MSG("seek unsuccessful @bpos %" PRIu64 ": %s", curPart.bpos, strerror(errno)); ++ thisPacket.null(); ++ return; ++ } ++ readPos = inFile.getPos(); ++ while (readPos+readBuffer.size() < curPart.bpos+curPart.size && inFile && keepRunning()){ ++ inFile.readSome((curPart.bpos+curPart.size) - (readPos+readBuffer.size()), *this); ++ } ++ if (readPos+readBuffer.size() < curPart.bpos+curPart.size){ ++ FAIL_MSG("Read retry unsuccessful at %" PRIu64 ", aborting", readPos+readBuffer.size()); ++ thisPacket.null(); ++ return; ++ } + } + + if (M.getCodec(curPart.trackID) == "subtitle"){ +- unsigned int txtLen = Bit::btohs(data); ++ unsigned int txtLen = Bit::btohs(readBuffer + (curPart.bpos-readPos)); + if (!txtLen && false){ + curPart.index++; + return getNext(idx); +@@ -499,14 +563,14 @@ namespace Mist{ + thisPack.null(); + thisPack["trackid"] = curPart.trackID; + thisPack["bpos"] = curPart.bpos; //(long long)fileSource.tellg(); +- thisPack["data"] = std::string(data + 2, txtLen); ++ thisPack["data"] = std::string(readBuffer + (curPart.bpos-readPos) + 2, txtLen); + thisPack["time"] = curPart.time; + if (curPart.duration){thisPack["duration"] = curPart.duration;} + thisPack["keyframe"] = true; + std::string tmpStr = thisPack.toNetPacked(); + thisPacket.reInit(tmpStr.data(), tmpStr.size()); + }else{ +- thisPacket.genericFill(curPart.time, curPart.offset, curPart.trackID, data, curPart.size, 0, isKeyframe); ++ thisPacket.genericFill(curPart.time, curPart.offset, curPart.trackID, readBuffer + (curPart.bpos-readPos), curPart.size, 0, isKeyframe); + } + thisTime = curPart.time; + thisIdx = curPart.trackID; +diff --git a/src/input/input_mp4.h b/src/input/input_mp4.h +index b5987d3b..4ab9f36e 100644 +--- a/src/input/input_mp4.h ++++ b/src/input/input_mp4.h +@@ -1,5 +1,6 @@ + #include "input.h" + #include <mist/dtsc.h> ++#include <mist/urireader.h> + #include <mist/mp4.h> + #include <mist/mp4_generic.h> + namespace Mist{ +@@ -70,10 +71,10 @@ namespace Mist{ + bool stco64; + }; + +- class inputMP4 : public Input{ ++ class inputMP4 : public Input, public Util::DataCallback { + public: + inputMP4(Util::Config *cfg); +- ~inputMP4(); ++ void dataCallback(const char *ptr, size_t size); + + protected: + // Private Functions +@@ -85,7 +86,10 @@ namespace Mist{ + void seek(uint64_t seekTime, size_t idx = INVALID_TRACK_ID); + void handleSeek(uint64_t seekTime, size_t idx); + +- FILE *inFile; ++ HTTP::URIReader inFile; ++ Util::ResizeablePointer readBuffer; ++ uint64_t readPos; ++ uint64_t bps; + + mp4TrackHeader &headerData(size_t trackID); + +@@ -94,11 +98,6 @@ namespace Mist{ + + // remember last seeked keyframe; + std::map<size_t, uint32_t> nextKeyframe; +- +- // these next two variables keep a buffer for reading from filepointer inFile; +- uint64_t malSize; +- char *data; ///\todo rename this variable to a more sensible name, it is a temporary piece of +- /// memory to read from files + }; + }// namespace Mist + +-- +2.25.1 + + +From 2740d65a0f5715c42eb6de24cbf610ba6271b85a Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Wed, 17 Aug 2022 10:54:31 +0200 +Subject: [PATCH 17/38] Improved RTP timestamp logging, fixed bug related to + firstTime value + +--- + lib/rtp.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/lib/rtp.cpp b/lib/rtp.cpp +index 3ed9b7c6..5a5ed829 100644 +--- a/lib/rtp.cpp ++++ b/lib/rtp.cpp +@@ -877,7 +877,7 @@ namespace RTP{ + if (!firstTime){ + milliSync = Util::bootMS(); + firstTime = pTime + 1; +- INFO_MSG("RTP timestamp rollover expected in " PRETTY_PRINT_TIME, ++ INFO_MSG("RTP timestamp rollover for %" PRIu64 " (%s) expected in " PRETTY_PRINT_TIME, trackId, codec.c_str(), + PRETTY_ARG_TIME((0xFFFFFFFFul - firstTime) / multiplier / 1000)); + }else{ + if (recentWrap){ +@@ -886,14 +886,15 @@ namespace RTP{ + }else{ + if (prevTime > pTime && pTime < 0x40000000lu && prevTime > 0x80000000lu){ + ++wrapArounds; ++ INFO_MSG("RTP timestamp rollover %" PRIu32 " for %" PRIu64 " (%s) happened; next should be in " PRETTY_PRINT_TIME, wrapArounds, trackId, codec.c_str(), PRETTY_ARG_TIME((0xFFFFFFFFul) / multiplier / 1000)); + recentWrap = true; + } + } + } + // When there are B-frames, the firstTime can be higher than the current time + // causing msTime to become negative and thus overflow +- if (firstTime > pTime + 1){ +- WARN_MSG("firstTime was higher than current packet time. Readjusting firsTime..."); ++ if (!wrapArounds && firstTime > pTime + 1){ ++ WARN_MSG("firstTime was higher than current packet time. Readjusting firstTime..."); + firstTime = pTime + 1; + } + prevTime = pkt.getTimeStamp(); +-- +2.25.1 + + +From 2870ae1cedd202755bbe9d0e6808086d40656157 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Wed, 24 Aug 2022 15:02:19 +0200 +Subject: [PATCH 18/38] =?UTF-8?q?SRT=20RAW=20fixup=20=F0=9F=A4=A6?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + src/input/input_tssrt.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/input/input_tssrt.cpp b/src/input/input_tssrt.cpp +index da69be29..4219ebbc 100644 +--- a/src/input/input_tssrt.cpp ++++ b/src/input/input_tssrt.cpp +@@ -211,7 +211,6 @@ namespace Mist{ + } + uint64_t packetTime = Util::bootMS(); + thisPacket.genericFill(packetTime, 0, 1, rawBuffer, rawBuffer.size(), 0, 0); +- bufferLivePacket(thisPacket); + lastRawPacket = packetTime; + rawBuffer.truncate(0); + return; +-- +2.25.1 + + +From a9ddc377895f5feb898c162de0f6b0363cf94276 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 25 Aug 2022 10:26:38 +0200 +Subject: [PATCH 19/38] =?UTF-8?q?Why,=20Haivision,=20why=3F=20=F0=9F=98=AD?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + lib/socket_srt.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/socket_srt.cpp b/lib/socket_srt.cpp +index 3e03bce4..6d1d5695 100644 +--- a/lib/socket_srt.cpp ++++ b/lib/socket_srt.cpp +@@ -392,6 +392,10 @@ namespace Socket{ + } + } + params["payloadsize"] = asString(chunkTransmitSize); ++ //This line forces the transmission type to live if unset. ++ //Live is actually the default, but not explicitly setting the option means ++ //that all other defaults do not get applied either, which is bad. ++ if (!params.count("transtype")){params["transtype"] = "live";} + } + + int SRTConnection::preConfigureSocket(){ +-- +2.25.1 + + +From 8aceff951d3e320786bf33c9ff558a506df372c6 Mon Sep 17 00:00:00 2001 +From: Marco van Dijk <marco@stronk.rocks> +Date: Mon, 29 Aug 2022 14:36:00 +0200 +Subject: [PATCH 20/38] Fix connections getting closed on interrupted system + call + +--- + lib/socket.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lib/socket.cpp b/lib/socket.cpp +index 865c3be7..6d63af00 100644 +--- a/lib/socket.cpp ++++ b/lib/socket.cpp +@@ -1032,6 +1032,7 @@ unsigned int Socket::Connection::iwrite(const void *buffer, int len){ + case MBEDTLS_ERR_SSL_WANT_WRITE: return 0; break; + case MBEDTLS_ERR_SSL_WANT_READ: return 0; break; + case EWOULDBLOCK: return 0; break; ++ case EINTR: return 0; break; + default: + Error = true; + lastErr = strerror(errno); +@@ -1071,6 +1072,7 @@ unsigned int Socket::Connection::iwrite(const void *buffer, int len){ + if (r < 0){ + switch (errno){ + case EWOULDBLOCK: return 0; break; ++ case EINTR: return 0; break; + default: + Error = true; + lastErr = strerror(errno); +-- +2.25.1 + + +From 54a46146c2527004a96b78fe8b7341eab4de6f62 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 11 Aug 2022 13:17:13 +0200 +Subject: [PATCH 21/38] Fix TS inputs taking more and more memory over time in + some cases + +--- + lib/ts_stream.cpp | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/lib/ts_stream.cpp b/lib/ts_stream.cpp +index 4ab20c59..8da72493 100644 +--- a/lib/ts_stream.cpp ++++ b/lib/ts_stream.cpp +@@ -190,7 +190,8 @@ namespace TS{ + uint32_t tid = newPack.getPID(); + bool unitStart = newPack.getUnitStart(); + static uint32_t wantPrev = 0; +- bool wantTrack = ((wantPrev == tid) || (tid == 0 || newPack.isPMT(pmtTracks) || pidToCodec.count(tid))); ++ bool isData = pidToCodec.count(tid); ++ bool wantTrack = ((wantPrev == tid) || (tid == 0 || newPack.isPMT(pmtTracks) || isData)); + if (!wantTrack){return;} + if (psCacheTid != tid || !psCache){ + psCache = &(pesStreams[tid]); +@@ -199,7 +200,7 @@ namespace TS{ + if (unitStart || !psCache->empty()){ + wantPrev = tid; + psCache->push_back(newPack); +- if (unitStart){ ++ if (unitStart && isData){ + pesPositions[tid].push_back(bytePos); + ++(seenUnitStart[tid]); + } +@@ -210,7 +211,7 @@ namespace TS{ + if (tid == 0){return false;} + { + tthread::lock_guard<tthread::recursive_mutex> guard(tMutex); +- return !pmtTracks.count(tid); ++ return pidToCodec.count(tid); + } + } + +@@ -280,6 +281,11 @@ namespace TS{ + } + + if (!pidToCodec.count(tid)){ ++ pesStreams.erase(tid); ++ pesPositions.erase(tid); ++ seenUnitStart.erase(tid); ++ psCacheTid = 0; ++ psCache = 0; + return; // skip unknown codecs + } + +-- +2.25.1 + + +From c10d5a7ec1fdc71cc4af2329a9030b422735fd34 Mon Sep 17 00:00:00 2001 +From: Marco van Dijk <marco@stronk.rocks> +Date: Wed, 16 Mar 2022 13:45:37 +0100 +Subject: [PATCH 22/38] onFail on a WS connection, send the error back using + the websocket request handler + +--- + src/output/output_http_internal.cpp | 20 ++++++++++++++++++-- + src/output/output_http_internal.h | 1 + + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/src/output/output_http_internal.cpp b/src/output/output_http_internal.cpp +index c8ca2e6c..97ca455f 100644 +--- a/src/output/output_http_internal.cpp ++++ b/src/output/output_http_internal.cpp +@@ -36,6 +36,7 @@ namespace Mist{ + + OutHTTP::OutHTTP(Socket::Connection &conn) : HTTPOutput(conn){ + stayConnected = false; ++ thisError = ""; + // If this connection is a socket and not already connected to stdio, connect it to stdio. + if (myConn.getPureSocket() != -1 && myConn.getSocket() != STDIN_FILENO && myConn.getSocket() != STDOUT_FILENO){ + std::string host = getConnectedHost(); +@@ -63,6 +64,11 @@ namespace Mist{ + bool OutHTTP::listenMode(){return !(config->getString("ip").size());} + + void OutHTTP::onFail(const std::string &msg, bool critical){ ++ // If we are connected through WS, the websockethandler should return the error message ++ if (stayConnected){ ++ thisError = msg; ++ return; ++ } + if (responded){ + HTTPOutput::onFail(msg, critical); + return; +@@ -78,7 +84,6 @@ namespace Mist{ + return; + } + if (H.url.size() >= 3 && H.url.substr(H.url.size() - 3) == ".js"){ +- if (websocketHandler()){return;} + JSON::Value json_resp; + json_resp["error"] = "Could not retrieve stream. Sorry."; + json_resp["error_guru"] = msg; +@@ -1149,12 +1154,23 @@ namespace Mist{ + if (meta){meta.reloadReplacedPagesIfNeeded();} + if (newState != prevState || (newState == STRMSTAT_READY && M.getValidTracks() != prevTracks)){ + if (newState == STRMSTAT_READY){ ++ thisError = ""; + reconnect(); + prevTracks = M.getValidTracks(); + }else{ + disconnect(); + } +- JSON::Value resp = getStatusJSON(reqHost, useragent); ++ JSON::Value resp; ++ // Check if we have an error message set ++ if (thisError == ""){ ++ resp = getStatusJSON(reqHost, useragent); ++ }else{ ++ resp["error"] = "Could not retrieve stream. Sorry."; ++ resp["error_guru"] = thisError; ++ if (config->getString("nostreamtext") != ""){ ++ resp["on_error"] = config->getString("nostreamtext"); ++ } ++ } + if (currStreamName != streamName){ + currStreamName = streamName; + snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamName.c_str()); +diff --git a/src/output/output_http_internal.h b/src/output/output_http_internal.h +index 0f939e78..774eb186 100644 +--- a/src/output/output_http_internal.h ++++ b/src/output/output_http_internal.h +@@ -21,6 +21,7 @@ namespace Mist{ + private: + std::string origStreamName; + std::string mistPath; ++ std::string thisError; + }; + }// namespace Mist + +-- +2.25.1 + + +From f418fed81c0c46fd338e238b558085f408456ed9 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 24 Mar 2022 15:20:52 +0100 +Subject: [PATCH 23/38] Fix HLS output not setting "responded" value + appropriately + +--- + src/output/output_hls.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp +index 19d083e6..ad810aa7 100644 +--- a/src/output/output_hls.cpp ++++ b/src/output/output_hls.cpp +@@ -232,6 +232,7 @@ namespace Mist{ + H.setCORSHeaders(); + if (H.method == "OPTIONS" || H.method == "HEAD"){ + H.SendResponse("200", "OK", myConn); ++ responded = true; + return; + } + H.SetBody("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM " +@@ -239,6 +240,7 @@ namespace Mist{ + "cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" " + "/><site-control permitted-cross-domain-policies=\"all\"/></cross-domain-policy>"); + H.SendResponse("200", "OK", myConn); ++ responded = true; + return; + }// crossdomain.xml + +@@ -262,6 +264,7 @@ namespace Mist{ + } + H.SetBody(""); + H.SendResponse("200", "OK", myConn); ++ responded = true; + return; + } + +@@ -311,6 +314,7 @@ namespace Mist{ + targetTime = HLS::getPartTargetTime(M, idx, mTrack, startTime, msn, part); + if (!targetTime){ + H.SendResponse("404", "Partial fragment does not exist", myConn); ++ responded = true; + return; + } + startTime += part * HLS::partDurationMaxMs; +@@ -372,6 +376,7 @@ namespace Mist{ + "served.\n"); + myConn.SendNow(H.BuildResponse("404", "Fragment out of range")); + WARN_MSG("Fragment @ %" PRIu64 " too old", startTime); ++ responded = true; + return; + } + +@@ -389,10 +394,12 @@ namespace Mist{ + } + if (H.method == "OPTIONS" || H.method == "HEAD"){ + H.SendResponse("200", "OK", myConn); ++ responded = true; + return; + } + + H.StartResponse(H, myConn, VLCworkaround || config->getBool("nonchunked")); ++ responded = true; + // we assume whole fragments - but timestamps may be altered at will + contPAT = fragmentIndex; // PAT continuity counter + contPMT = fragmentIndex; // PMT continuity counter +@@ -419,6 +426,7 @@ namespace Mist{ + // Strip /hls/<streamname>/ from url + std::string url = H.url.substr(H.url.find('/', 5) + 1); + sendHlsManifest(url); ++ responded = true; + } + } + +-- +2.25.1 + + +From f3c003481d572c140643e9bbfb292942d8e2ed38 Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Mon, 26 Sep 2022 12:44:30 +0200 +Subject: [PATCH 24/38] Made FLV memory-based loader functions use const + pointers + +--- + lib/flv_tag.cpp | 6 +++--- + lib/flv_tag.h | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/lib/flv_tag.cpp b/lib/flv_tag.cpp +index 9ccb6c41..780c6c5a 100644 +--- a/lib/flv_tag.cpp ++++ b/lib/flv_tag.cpp +@@ -49,7 +49,7 @@ bool FLV::check_header(char *header){ + + /// Checks the first 3 bytes for the string "FLV". Implementing a basic FLV header check, + /// returning true if it is, false if not. +-bool FLV::is_header(char *header){ ++bool FLV::is_header(const char *header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; +@@ -624,7 +624,7 @@ bool FLV::Tag::ChunkLoader(const RTMPStream::Chunk &O){ + /// \param S The size of the data buffer. + /// \param P The current position in the data buffer. Will be updated to reflect new position. + /// \return True if count bytes are read succesfully, false otherwise. +-bool FLV::Tag::MemReadUntil(char *buffer, unsigned int count, unsigned int &sofar, char *D, ++bool FLV::Tag::MemReadUntil(char *buffer, unsigned int count, unsigned int &sofar, const char *D, + unsigned int S, unsigned int &P){ + if (sofar >= count){return true;} + int r = 0; +@@ -646,7 +646,7 @@ bool FLV::Tag::MemReadUntil(char *buffer, unsigned int count, unsigned int &sofa + /// location of the data buffer. \param S The size of the data buffer. \param P The current position + /// in the data buffer. Will be updated to reflect new position. \return True if a whole tag is + /// succesfully read, false otherwise. +-bool FLV::Tag::MemLoader(char *D, unsigned int S, unsigned int &P){ ++bool FLV::Tag::MemLoader(const char *D, unsigned int S, unsigned int &P){ + if (len < 15){len = 15;} + if (!checkBufferSize()){return false;} + if (done){ +diff --git a/lib/flv_tag.h b/lib/flv_tag.h +index ca27f472..10f616b9 100644 +--- a/lib/flv_tag.h ++++ b/lib/flv_tag.h +@@ -22,7 +22,7 @@ namespace FLV{ + + // functions + bool check_header(char *header); ///< Checks a FLV Header for validness. +- bool is_header(char *header); ///< Checks the first 3 bytes for the string "FLV". ++ bool is_header(const char *header); ///< Checks the first 3 bytes for the string "FLV". + + /// Helper function that can quickly skip through a file looking for a particular tag type + bool seekToTagType(FILE *f, uint8_t type); +@@ -55,7 +55,7 @@ namespace FLV{ + bool DTSCMetaInit(const DTSC::Meta &M, std::set<size_t> &selTracks); + void toMeta(DTSC::Meta &meta, AMF::Object &amf_storage); + void toMeta(DTSC::Meta &meta, AMF::Object &amf_storage, size_t &reTrack, const std::map<std::string, std::string> &targetParams); +- bool MemLoader(char *D, unsigned int S, unsigned int &P); ++ bool MemLoader(const char *D, unsigned int S, unsigned int &P); + bool FileLoader(FILE *f); + unsigned int getTrackID(); + char *getData(); +@@ -68,7 +68,7 @@ namespace FLV{ + void setLen(); + bool checkBufferSize(); + // loader helper functions +- bool MemReadUntil(char *buffer, unsigned int count, unsigned int &sofar, char *D, ++ bool MemReadUntil(char *buffer, unsigned int count, unsigned int &sofar, const char *D, + unsigned int S, unsigned int &P); + bool FileReadUntil(char *buffer, unsigned int count, unsigned int &sofar, FILE *f); + }; +-- +2.25.1 + + +From 3e85da2afd1b3d36290763eebf84dd66ad08636c Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Mon, 19 Sep 2022 17:26:15 +0200 +Subject: [PATCH 25/38] Match libav's RTMP receive window rollover behaviour + +--- + lib/rtmpchunks.cpp | 5 +++++ + src/output/output_rtmp.cpp | 2 +- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lib/rtmpchunks.cpp b/lib/rtmpchunks.cpp +index e7c151f0..5f9d33f0 100644 +--- a/lib/rtmpchunks.cpp ++++ b/lib/rtmpchunks.cpp +@@ -475,6 +475,11 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer &buffer){ + } + lastrecv[cs_id] = *this; + RTMPStream::rec_cnt += i + real_len; ++ if (RTMPStream::rec_cnt >= 0xf0000000){ ++ INFO_MSG("Resetting receive window due to impending rollover"); ++ RTMPStream::rec_cnt -= 0xf0000000; ++ RTMPStream::rec_window_at = 0; ++ } + if (len_left == 0){ + return true; + }else{ +diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp +index 16a400d0..23194f4a 100644 +--- a/src/output/output_rtmp.cpp ++++ b/src/output/output_rtmp.cpp +@@ -1599,7 +1599,7 @@ namespace Mist{ + while (next.Parse(inputBuffer)){ + + // send ACK if we received a whole window +- if ((RTMPStream::rec_cnt - RTMPStream::rec_window_at > RTMPStream::rec_window_size) || Util::bootSecs() > lastAck+15){ ++ if ((RTMPStream::rec_cnt - RTMPStream::rec_window_at > RTMPStream::rec_window_size / 4) || Util::bootSecs() > lastAck+15){ + lastAck = Util::bootSecs(); + RTMPStream::rec_window_at = RTMPStream::rec_cnt; + myConn.SendNow(RTMPStream::SendCTL(3, RTMPStream::rec_cnt)); // send ack (msg 3) +-- +2.25.1 + + +From 074e7570284a094c12b00b88aa5cdf4a8f7fe5e4 Mon Sep 17 00:00:00 2001 +From: Ramkoemar <rbhoera@gmail.com> +Date: Mon, 18 Oct 2021 14:29:13 +0200 +Subject: [PATCH 26/38] Sessions rework + +--- + CMakeLists.txt | 11 + + lib/comms.cpp | 428 +++++--- + lib/comms.h | 50 +- + lib/defines.h | 7 +- + src/controller/controller.cpp | 1 - + src/controller/controller_api.cpp | 1 + + src/controller/controller_statistics.cpp | 1185 ++++++++-------------- + src/controller/controller_statistics.h | 61 +- + src/controller/controller_storage.cpp | 22 +- + src/input/input.cpp | 12 +- + src/input/input.h | 2 +- + src/input/input_rtsp.cpp | 5 +- + src/input/input_sdp.cpp | 5 +- + src/input/input_ts.cpp | 5 +- + src/input/input_tssrt.cpp | 2 +- + src/input/input_tssrt.h | 2 +- + src/output/output.cpp | 125 +-- + src/output/output.h | 9 +- + src/output/output_cmaf.cpp | 2 +- + src/output/output_cmaf.h | 3 +- + src/output/output_http.cpp | 28 +- + src/output/output_tssrt.cpp | 2 +- + src/output/output_tssrt.h | 2 +- + src/output/output_webrtc.cpp | 2 +- + src/output/output_webrtc.h | 2 +- + src/process/process_exec.cpp | 4 +- + src/session.cpp | 367 +++++++ + 27 files changed, 1192 insertions(+), 1153 deletions(-) + create mode 100644 src/session.cpp + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 0e9bd644..6af16808 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -592,6 +592,17 @@ makeOutput(RTSP rtsp)#LTS + makeOutput(WAV wav)#LTS + makeOutput(SDP sdp http) + ++add_executable(MistSession ++ ${BINARY_DIR}/mist/.headers ++ src/session.cpp ++) ++install( ++ TARGETS MistSession ++ DESTINATION bin ++) ++target_link_libraries(MistSession mist) ++ ++ + add_executable(MistProcFFMPEG + ${BINARY_DIR}/mist/.headers + src/process/process_ffmpeg.cpp +diff --git a/lib/comms.cpp b/lib/comms.cpp +index 108c686a..85f1e6d7 100644 +--- a/lib/comms.cpp ++++ b/lib/comms.cpp +@@ -7,6 +7,7 @@ + #include "timing.h" + #include <fcntl.h> + #include <string.h> ++#include "config.h" + + namespace Comms{ + Comms::Comms(){ +@@ -141,22 +142,197 @@ namespace Comms{ + } + } + +- Statistics::Statistics() : Comms(){sem.open(SEM_STATISTICS, O_CREAT | O_RDWR, ACCESSPERMS, 1);} ++ Sessions::Sessions() : Connections(){sem.open(SEM_STATISTICS, O_CREAT | O_RDWR, ACCESSPERMS, 1);} + +- void Statistics::unload(){ +- if (index != INVALID_RECORD_INDEX){ +- setStatus(COMM_STATUS_DISCONNECT | getStatus()); ++ void Sessions::reload(bool _master, bool reIssue){ ++ Comms::reload(COMMS_STATISTICS, COMMS_STATISTICS_INITSIZE, _master, reIssue); ++ } ++ ++ std::string Sessions::getSessId() const{return sessId.string(index);} ++ std::string Sessions::getSessId(size_t idx) const{return (master ? sessId.string(idx) : 0);} ++ void Sessions::setSessId(std::string _sid){sessId.set(_sid, index);} ++ void Sessions::setSessId(std::string _sid, size_t idx){ ++ if (!master){return;} ++ sessId.set(_sid, idx); ++ } ++ ++ bool Sessions::sessIdExists(std::string _sid){ ++ for (size_t i = 0; i < recordCount(); i++){ ++ if (getStatus(i) == COMM_STATUS_INVALID || (getStatus(i) & COMM_STATUS_DISCONNECT)){continue;} ++ if (getSessId(i) == _sid){ ++ if (Util::Procs::isRunning(getPid(i))){ ++ return true; ++ } ++ } + } +- index = INVALID_RECORD_INDEX; ++ return false; + } + +- void Statistics::reload(bool _master, bool reIssue){ +- Comms::reload(COMMS_STATISTICS, COMMS_STATISTICS_INITSIZE, _master, reIssue); ++ void Sessions::addFields(){ ++ Connections::addFields(); ++ dataAccX.addField("sessid", RAX_STRING, 80); + } + +- void Statistics::addFields(){ ++ void Sessions::nullFields(){ ++ Connections::nullFields(); ++ setSessId(""); ++ } ++ ++ void Sessions::fieldAccess(){ ++ Connections::fieldAccess(); ++ sessId = dataAccX.getFieldAccX("sessid"); ++ } ++ ++ Users::Users() : Comms(){} ++ ++ Users::Users(const Users &rhs) : Comms(){ ++ if (rhs){ ++ reload(rhs.streamName, (size_t)rhs.getTrack()); ++ if (*this){ ++ setKeyNum(rhs.getKeyNum()); ++ setTrack(rhs.getTrack()); ++ } ++ } ++ } ++ ++ void Users::reload(const std::string &_streamName, bool _master, bool reIssue){ ++ streamName = _streamName; ++ ++ char semName[NAME_BUFFER_SIZE]; ++ snprintf(semName, NAME_BUFFER_SIZE, SEM_USERS, streamName.c_str()); ++ sem.open(semName, O_CREAT | O_RDWR, ACCESSPERMS, 1); ++ ++ char userPageName[NAME_BUFFER_SIZE]; ++ snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_USERS, streamName.c_str()); ++ ++ Comms::reload(userPageName, COMMS_USERS_INITSIZE, _master, reIssue); ++ } ++ ++ void Users::addFields(){ ++ Comms::addFields(); ++ dataAccX.addField("track", RAX_64UINT); ++ dataAccX.addField("keynum", RAX_64UINT); ++ } ++ ++ void Users::nullFields(){ ++ Comms::nullFields(); ++ setTrack(0); ++ setKeyNum(0); ++ } ++ ++ void Users::fieldAccess(){ ++ Comms::fieldAccess(); ++ track = dataAccX.getFieldAccX("track"); ++ keyNum = dataAccX.getFieldAccX("keynum"); ++ } ++ ++ void Users::reload(const std::string &_streamName, size_t idx, uint8_t initialState){ ++ reload(_streamName); ++ if (dataPage){ ++ setTrack(idx); ++ setKeyNum(0); ++ setStatus(initialState); ++ } ++ } ++ ++ uint32_t Users::getTrack() const{return track.uint(index);} ++ uint32_t Users::getTrack(size_t idx) const{return (master ? track.uint(idx) : 0);} ++ void Users::setTrack(uint32_t _track){track.set(_track, index);} ++ void Users::setTrack(uint32_t _track, size_t idx){ ++ if (!master){return;} ++ track.set(_track, idx); ++ } ++ ++ size_t Users::getKeyNum() const{return keyNum.uint(index);} ++ size_t Users::getKeyNum(size_t idx) const{return (master ? keyNum.uint(idx) : 0);} ++ void Users::setKeyNum(size_t _keyNum){keyNum.set(_keyNum, index);} ++ void Users::setKeyNum(size_t _keyNum, size_t idx){ ++ if (!master){return;} ++ keyNum.set(_keyNum, idx); ++ } ++ ++ /// \brief Claims a spot on the connections page for the input/output which calls this function ++ /// Starts the MistSession binary for each session, which handles the statistics ++ /// and the USER_NEW and USER_END triggers ++ /// \param streamName: Name of the stream the input is providing or an output is making available to viewers ++ /// \param ip: IP address of the viewer which wants to access streamName. For inputs this value can be set to any value ++ /// \param sid: Session ID given by the player or randomly generated ++ /// \param protocol: Protocol currently in use for this connection ++ /// \param sessionMode: Determines how a viewer session is defined: ++ // If set to 0, all connections with the same viewer IP and stream name are bundled. ++ // If set to 1, all connections with the same viewer IP and player ID are bundled. ++ // If set to 2, all connections with the same player ID and stream name are bundled. ++ // If set to 3, all connections with the same viewer IP, player ID and stream name are bundled. ++ /// \param _master: If True, we are reading from this page. If False, we are writing (to our entry) on this page ++ /// \param reIssue: If True, claim a new entry on this page ++ void Connections::reload(std::string streamName, std::string ip, std::string sid, std::string protocol, std::string reqUrl, uint64_t sessionMode, bool _master, bool reIssue){ ++ if (sessionMode == 0xFFFFFFFFFFFFFFFFull){ ++ FAIL_MSG("The session mode was not initialised properly. Assuming default behaviour of bundling by viewer IP, stream name and player id"); ++ sessionMode = SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID; ++ } ++ // Generate a unique session ID for each viewer, input or output ++ sessionId = generateSession(streamName, ip, sid, protocol, sessionMode); ++ if (protocol.size() >= 6 && protocol.substr(0, 6) == "INPUT:"){ ++ sessionId = "I" + sessionId; ++ }else if (protocol.size() >= 7 && protocol.substr(0, 7) == "OUTPUT:"){ ++ sessionId = "O" + sessionId; ++ } ++ char userPageName[NAME_BUFFER_SIZE]; ++ snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_SESSIONS, sessionId.c_str()); ++ // Check if the page exists, if not, spawn new session process ++ if (!_master){ ++ dataPage.init(userPageName, 0, false, false); ++ if (!dataPage){ ++ pid_t thisPid; ++ std::deque<std::string> args; ++ args.push_back(Util::getMyPath() + "MistSession"); ++ args.push_back(sessionId); ++ args.push_back("--sessionmode"); ++ args.push_back(JSON::Value(sessionMode).asString()); ++ args.push_back("--streamname"); ++ args.push_back(streamName); ++ args.push_back("--ip"); ++ args.push_back(ip); ++ args.push_back("--sid"); ++ args.push_back(sid); ++ args.push_back("--protocol"); ++ args.push_back(protocol); ++ args.push_back("--requrl"); ++ args.push_back(reqUrl); ++ int err = fileno(stderr); ++ thisPid = Util::Procs::StartPiped(args, 0, 0, &err); ++ Util::Procs::forget(thisPid); ++ HIGH_MSG("Spawned new session executeable (pid %u) for sessionId '%s', corresponding to host %s and stream %s", thisPid, sessionId.c_str(), ip.c_str(), streamName.c_str()); ++ } ++ } ++ // Open SEM_SESSION ++ if(!sem){ ++ char semName[NAME_BUFFER_SIZE]; ++ snprintf(semName, NAME_BUFFER_SIZE, SEM_SESSION, sessionId.c_str()); ++ sem.open(semName, O_RDWR, ACCESSPERMS, 1); ++ } ++ Comms::reload(userPageName, COMMS_SESSIONS_INITSIZE, _master, reIssue); ++ VERYHIGH_MSG("Reloading connection. Claimed record %lu", index); ++ } ++ ++ /// \brief Marks the data page as closed, so that we longer write any new data to is ++ void Connections::setExit(){ ++ if (!master){return;} ++ dataAccX.setExit(); ++ } ++ ++ bool Connections::getExit(){ ++ return dataAccX.isExit(); ++ } ++ ++ void Connections::unload(){ ++ if (index != INVALID_RECORD_INDEX){ ++ setStatus(COMM_STATUS_DISCONNECT | getStatus()); ++ } ++ index = INVALID_RECORD_INDEX; ++ } ++ void Connections::addFields(){ + Comms::addFields(); +- dataAccX.addField("sync", RAX_UINT); + dataAccX.addField("now", RAX_64UINT); + dataAccX.addField("time", RAX_64UINT); + dataAccX.addField("lastsecond", RAX_64UINT); +@@ -165,15 +341,15 @@ namespace Comms{ + dataAccX.addField("host", RAX_RAW, 16); + dataAccX.addField("stream", RAX_STRING, 100); + dataAccX.addField("connector", RAX_STRING, 20); +- dataAccX.addField("crc", RAX_32UINT); ++ dataAccX.addField("tags", RAX_STRING, 512); + dataAccX.addField("pktcount", RAX_64UINT); + dataAccX.addField("pktloss", RAX_64UINT); + dataAccX.addField("pktretrans", RAX_64UINT); + } + +- void Statistics::nullFields(){ ++ void Connections::nullFields(){ + Comms::nullFields(); +- setCRC(0); ++ setTags(""); + setConnector(""); + setStream(""); + setHost(""); +@@ -182,15 +358,13 @@ namespace Comms{ + setLastSecond(0); + setTime(0); + setNow(0); +- setSync(0); + setPacketCount(0); + setPacketLostCount(0); + setPacketRetransmitCount(0); + } + +- void Statistics::fieldAccess(){ ++ void Connections::fieldAccess(){ + Comms::fieldAccess(); +- sync = dataAccX.getFieldAccX("sync"); + now = dataAccX.getFieldAccX("now"); + time = dataAccX.getFieldAccX("time"); + lastSecond = dataAccX.getFieldAccX("lastsecond"); +@@ -199,209 +373,159 @@ namespace Comms{ + host = dataAccX.getFieldAccX("host"); + stream = dataAccX.getFieldAccX("stream"); + connector = dataAccX.getFieldAccX("connector"); +- crc = dataAccX.getFieldAccX("crc"); ++ tags = dataAccX.getFieldAccX("tags"); + pktcount = dataAccX.getFieldAccX("pktcount"); + pktloss = dataAccX.getFieldAccX("pktloss"); + pktretrans = dataAccX.getFieldAccX("pktretrans"); + } + +- uint8_t Statistics::getSync() const{return sync.uint(index);} +- uint8_t Statistics::getSync(size_t idx) const{return (master ? sync.uint(idx) : 0);} +- void Statistics::setSync(uint8_t _sync){sync.set(_sync, index);} +- void Statistics::setSync(uint8_t _sync, size_t idx){ +- if (!master){return;} +- sync.set(_sync, idx); +- } +- +- uint64_t Statistics::getNow() const{return now.uint(index);} +- uint64_t Statistics::getNow(size_t idx) const{return (master ? now.uint(idx) : 0);} +- void Statistics::setNow(uint64_t _now){now.set(_now, index);} +- void Statistics::setNow(uint64_t _now, size_t idx){ ++ uint64_t Connections::getNow() const{return now.uint(index);} ++ uint64_t Connections::getNow(size_t idx) const{return (master ? now.uint(idx) : 0);} ++ void Connections::setNow(uint64_t _now){now.set(_now, index);} ++ void Connections::setNow(uint64_t _now, size_t idx){ + if (!master){return;} + now.set(_now, idx); + } + +- uint64_t Statistics::getTime() const{return time.uint(index);} +- uint64_t Statistics::getTime(size_t idx) const{return (master ? time.uint(idx) : 0);} +- void Statistics::setTime(uint64_t _time){time.set(_time, index);} +- void Statistics::setTime(uint64_t _time, size_t idx){ ++ uint64_t Connections::getTime() const{return time.uint(index);} ++ uint64_t Connections::getTime(size_t idx) const{return (master ? time.uint(idx) : 0);} ++ void Connections::setTime(uint64_t _time){time.set(_time, index);} ++ void Connections::setTime(uint64_t _time, size_t idx){ + if (!master){return;} + time.set(_time, idx); + } + +- uint64_t Statistics::getLastSecond() const{return lastSecond.uint(index);} +- uint64_t Statistics::getLastSecond(size_t idx) const{ ++ uint64_t Connections::getLastSecond() const{return lastSecond.uint(index);} ++ uint64_t Connections::getLastSecond(size_t idx) const{ + return (master ? lastSecond.uint(idx) : 0); + } +- void Statistics::setLastSecond(uint64_t _lastSecond){lastSecond.set(_lastSecond, index);} +- void Statistics::setLastSecond(uint64_t _lastSecond, size_t idx){ ++ void Connections::setLastSecond(uint64_t _lastSecond){lastSecond.set(_lastSecond, index);} ++ void Connections::setLastSecond(uint64_t _lastSecond, size_t idx){ + if (!master){return;} + lastSecond.set(_lastSecond, idx); + } + +- uint64_t Statistics::getDown() const{return down.uint(index);} +- uint64_t Statistics::getDown(size_t idx) const{return (master ? down.uint(idx) : 0);} +- void Statistics::setDown(uint64_t _down){down.set(_down, index);} +- void Statistics::setDown(uint64_t _down, size_t idx){ ++ uint64_t Connections::getDown() const{return down.uint(index);} ++ uint64_t Connections::getDown(size_t idx) const{return (master ? down.uint(idx) : 0);} ++ void Connections::setDown(uint64_t _down){down.set(_down, index);} ++ void Connections::setDown(uint64_t _down, size_t idx){ + if (!master){return;} + down.set(_down, idx); + } + +- uint64_t Statistics::getUp() const{return up.uint(index);} +- uint64_t Statistics::getUp(size_t idx) const{return (master ? up.uint(idx) : 0);} +- void Statistics::setUp(uint64_t _up){up.set(_up, index);} +- void Statistics::setUp(uint64_t _up, size_t idx){ ++ uint64_t Connections::getUp() const{return up.uint(index);} ++ uint64_t Connections::getUp(size_t idx) const{return (master ? up.uint(idx) : 0);} ++ void Connections::setUp(uint64_t _up){up.set(_up, index);} ++ void Connections::setUp(uint64_t _up, size_t idx){ + if (!master){return;} + up.set(_up, idx); + } + +- std::string Statistics::getHost() const{return std::string(host.ptr(index), 16);} +- std::string Statistics::getHost(size_t idx) const{ ++ std::string Connections::getHost() const{return std::string(host.ptr(index), 16);} ++ std::string Connections::getHost(size_t idx) const{ + if (!master){return std::string((size_t)16, (char)'\000');} + return std::string(host.ptr(idx), 16); + } +- void Statistics::setHost(std::string _host){host.set(_host, index);} +- void Statistics::setHost(std::string _host, size_t idx){ ++ void Connections::setHost(std::string _host){host.set(_host, index);} ++ void Connections::setHost(std::string _host, size_t idx){ + if (!master){return;} + host.set(_host, idx); + } + +- std::string Statistics::getStream() const{return stream.string(index);} +- std::string Statistics::getStream(size_t idx) const{return (master ? stream.string(idx) : "");} +- void Statistics::setStream(std::string _stream){stream.set(_stream, index);} +- void Statistics::setStream(std::string _stream, size_t idx){ ++ std::string Connections::getStream() const{return stream.string(index);} ++ std::string Connections::getStream(size_t idx) const{return (master ? stream.string(idx) : "");} ++ void Connections::setStream(std::string _stream){stream.set(_stream, index);} ++ void Connections::setStream(std::string _stream, size_t idx){ + if (!master){return;} + stream.set(_stream, idx); + } + +- std::string Statistics::getConnector() const{return connector.string(index);} +- std::string Statistics::getConnector(size_t idx) const{ ++ std::string Connections::getConnector() const{return connector.string(index);} ++ std::string Connections::getConnector(size_t idx) const{ + return (master ? connector.string(idx) : ""); + } +- void Statistics::setConnector(std::string _connector){connector.set(_connector, index);} +- void Statistics::setConnector(std::string _connector, size_t idx){ ++ void Connections::setConnector(std::string _connector){connector.set(_connector, index);} ++ void Connections::setConnector(std::string _connector, size_t idx){ + if (!master){return;} + connector.set(_connector, idx); + } + +- uint32_t Statistics::getCRC() const{return crc.uint(index);} +- uint32_t Statistics::getCRC(size_t idx) const{return (master ? crc.uint(idx) : 0);} +- void Statistics::setCRC(uint32_t _crc){crc.set(_crc, index);} +- void Statistics::setCRC(uint32_t _crc, size_t idx){ ++ bool Connections::hasConnector(size_t idx, std::string protocol){ ++ std::stringstream sstream(connector.string(idx)); ++ std::string _conn; ++ while (std::getline(sstream, _conn, ',')){ ++ if (_conn == protocol){ ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ std::string Connections::getTags() const{return tags.string(index);} ++ std::string Connections::getTags(size_t idx) const{return (master ? tags.string(idx) : 0);} ++ void Connections::setTags(std::string _sid){tags.set(_sid, index);} ++ void Connections::setTags(std::string _sid, size_t idx){ + if (!master){return;} +- crc.set(_crc, idx); ++ tags.set(_sid, idx); + } + +- uint64_t Statistics::getPacketCount() const{return pktcount.uint(index);} +- uint64_t Statistics::getPacketCount(size_t idx) const{ ++ uint64_t Connections::getPacketCount() const{return pktcount.uint(index);} ++ uint64_t Connections::getPacketCount(size_t idx) const{ + return (master ? pktcount.uint(idx) : 0); + } +- void Statistics::setPacketCount(uint64_t _count){pktcount.set(_count, index);} +- void Statistics::setPacketCount(uint64_t _count, size_t idx){ ++ void Connections::setPacketCount(uint64_t _count){pktcount.set(_count, index);} ++ void Connections::setPacketCount(uint64_t _count, size_t idx){ + if (!master){return;} + pktcount.set(_count, idx); + } + +- uint64_t Statistics::getPacketLostCount() const{return pktloss.uint(index);} +- uint64_t Statistics::getPacketLostCount(size_t idx) const{ ++ uint64_t Connections::getPacketLostCount() const{return pktloss.uint(index);} ++ uint64_t Connections::getPacketLostCount(size_t idx) const{ + return (master ? pktloss.uint(idx) : 0); + } +- void Statistics::setPacketLostCount(uint64_t _lost){pktloss.set(_lost, index);} +- void Statistics::setPacketLostCount(uint64_t _lost, size_t idx){ ++ void Connections::setPacketLostCount(uint64_t _lost){pktloss.set(_lost, index);} ++ void Connections::setPacketLostCount(uint64_t _lost, size_t idx){ + if (!master){return;} + pktloss.set(_lost, idx); + } + +- uint64_t Statistics::getPacketRetransmitCount() const{return pktretrans.uint(index);} +- uint64_t Statistics::getPacketRetransmitCount(size_t idx) const{ ++ uint64_t Connections::getPacketRetransmitCount() const{return pktretrans.uint(index);} ++ uint64_t Connections::getPacketRetransmitCount(size_t idx) const{ + return (master ? pktretrans.uint(idx) : 0); + } +- void Statistics::setPacketRetransmitCount(uint64_t _retrans){pktretrans.set(_retrans, index);} +- void Statistics::setPacketRetransmitCount(uint64_t _retrans, size_t idx){ ++ void Connections::setPacketRetransmitCount(uint64_t _retrans){pktretrans.set(_retrans, index);} ++ void Connections::setPacketRetransmitCount(uint64_t _retrans, size_t idx){ + if (!master){return;} + pktretrans.set(_retrans, idx); + } + +- std::string Statistics::getSessId() const{return getSessId(index);} +- +- std::string Statistics::getSessId(size_t idx) const{ +- char res[140]; +- memset(res, 0, 140); +- std::string tmp = host.string(idx); +- memcpy(res, tmp.c_str(), (tmp.size() > 16 ? 16 : tmp.size())); +- tmp = stream.string(idx); +- memcpy(res + 16, tmp.c_str(), (tmp.size() > 100 ? 100 : tmp.size())); +- tmp = connector.string(idx); +- memcpy(res + 116, tmp.c_str(), (tmp.size() > 20 ? 20 : tmp.size())); +- Bit::htobl(res + 136, crc.uint(idx)); +- return Secure::md5(res, 140); +- } +- +- Users::Users() : Comms(){} +- +- Users::Users(const Users &rhs) : Comms(){ +- if (rhs){ +- reload(rhs.streamName, (size_t)rhs.getTrack()); +- if (*this){ +- setKeyNum(rhs.getKeyNum()); +- setTrack(rhs.getTrack()); +- } ++ /// \brief Generates a session ID which is unique per viewer ++ /// \return generated session ID as string ++ std::string Connections::generateSession(std::string streamName, std::string ip, std::string sid, std::string connector, uint64_t sessionMode){ ++ std::string concat; ++ // First bit defines whether to include stream name ++ if (sessionMode > 7){ ++ concat += streamName; ++ sessionMode -= 8; + } +- } +- +- void Users::reload(const std::string &_streamName, bool _master, bool reIssue){ +- streamName = _streamName; +- +- char semName[NAME_BUFFER_SIZE]; +- snprintf(semName, NAME_BUFFER_SIZE, SEM_USERS, streamName.c_str()); +- sem.open(semName, O_CREAT | O_RDWR, ACCESSPERMS, 1); +- +- char userPageName[NAME_BUFFER_SIZE]; +- snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_USERS, streamName.c_str()); +- +- Comms::reload(userPageName, COMMS_USERS_INITSIZE, _master, reIssue); +- } +- +- void Users::addFields(){ +- Comms::addFields(); +- dataAccX.addField("track", RAX_64UINT); +- dataAccX.addField("keynum", RAX_64UINT); +- } +- +- void Users::nullFields(){ +- Comms::nullFields(); +- setTrack(0); +- setKeyNum(0); +- } +- +- void Users::fieldAccess(){ +- Comms::fieldAccess(); +- track = dataAccX.getFieldAccX("track"); +- keyNum = dataAccX.getFieldAccX("keynum"); +- } +- +- void Users::reload(const std::string &_streamName, size_t idx, uint8_t initialState){ +- reload(_streamName); +- if (dataPage){ +- setTrack(idx); +- setKeyNum(0); +- setStatus(initialState); ++ // Second bit defines whether to include viewer ip ++ if (sessionMode > 3){ ++ concat += ip; ++ sessionMode -= 4; + } +- } +- +- uint32_t Users::getTrack() const{return track.uint(index);} +- uint32_t Users::getTrack(size_t idx) const{return (master ? track.uint(idx) : 0);} +- void Users::setTrack(uint32_t _track){track.set(_track, index);} +- void Users::setTrack(uint32_t _track, size_t idx){ +- if (!master){return;} +- track.set(_track, idx); +- } +- +- size_t Users::getKeyNum() const{return keyNum.uint(index);} +- size_t Users::getKeyNum(size_t idx) const{return (master ? keyNum.uint(idx) : 0);} +- void Users::setKeyNum(size_t _keyNum){keyNum.set(_keyNum, index);} +- void Users::setKeyNum(size_t _keyNum, size_t idx){ +- if (!master){return;} +- keyNum.set(_keyNum, idx); ++ // Third bit defines whether to include player ip ++ if (sessionMode > 1){ ++ concat += sid; ++ sessionMode -= 2; ++ } ++ // Fourth bit defines whether to include protocol ++ if (sessionMode == 1){ ++ concat += connector; ++ sessionMode = 0; ++ } ++ if (sessionMode > 0){ ++ WARN_MSG("Could not resolve session mode of value %lu", sessionMode); ++ } ++ return Secure::sha256(concat.c_str(), concat.length()); + } + }// namespace Comms +diff --git a/lib/comms.h b/lib/comms.h +index 9f459422..9a5c0ea9 100644 +--- a/lib/comms.h ++++ b/lib/comms.h +@@ -64,21 +64,21 @@ namespace Comms{ + Util::FieldAccX pid; + }; + +- class Statistics : public Comms{ ++ class Connections : public Comms{ + public: +- Statistics(); +- operator bool() const{return dataPage.mapped && (master || index != INVALID_RECORD_INDEX);} ++ void reload(std::string streamName, std::string ip, std::string sid, std::string protocol, std::string reqUrl, uint64_t sessionMode, bool _master = false, bool reIssue = false); + void unload(); +- void reload(bool _master = false, bool reIssue = false); ++ operator bool() const{return dataPage.mapped && (master || index != INVALID_RECORD_INDEX);} ++ std::string generateSession(std::string streamName, std::string ip, std::string sid, std::string connector, uint64_t sessionMode); ++ std::string sessionId; ++ ++ void setExit(); ++ bool getExit(); ++ + virtual void addFields(); + virtual void nullFields(); + virtual void fieldAccess(); + +- uint8_t getSync() const; +- uint8_t getSync(size_t idx) const; +- void setSync(uint8_t _sync); +- void setSync(uint8_t _sync, size_t idx); +- + uint64_t getNow() const; + uint64_t getNow(size_t idx) const; + void setNow(uint64_t _now); +@@ -118,11 +118,12 @@ namespace Comms{ + std::string getConnector(size_t idx) const; + void setConnector(std::string _connector); + void setConnector(std::string _connector, size_t idx); ++ bool hasConnector(size_t idx, std::string protocol); + +- uint32_t getCRC() const; +- uint32_t getCRC(size_t idx) const; +- void setCRC(uint32_t _crc); +- void setCRC(uint32_t _crc, size_t idx); ++ std::string getTags() const; ++ std::string getTags(size_t idx) const; ++ void setTags(std::string _sid); ++ void setTags(std::string _sid, size_t idx); + + uint64_t getPacketCount() const; + uint64_t getPacketCount(size_t idx) const; +@@ -139,11 +140,7 @@ namespace Comms{ + void setPacketRetransmitCount(uint64_t _retransmit); + void setPacketRetransmitCount(uint64_t _retransmit, size_t idx); + +- std::string getSessId() const; +- std::string getSessId(size_t index) const; +- +- private: +- Util::FieldAccX sync; ++ protected: + Util::FieldAccX now; + Util::FieldAccX time; + Util::FieldAccX lastSecond; +@@ -152,7 +149,8 @@ namespace Comms{ + Util::FieldAccX host; + Util::FieldAccX stream; + Util::FieldAccX connector; +- Util::FieldAccX crc; ++ Util::FieldAccX sessId; ++ Util::FieldAccX tags; + Util::FieldAccX pktcount; + Util::FieldAccX pktloss; + Util::FieldAccX pktretrans; +@@ -186,4 +184,18 @@ namespace Comms{ + Util::FieldAccX track; + Util::FieldAccX keyNum; + }; ++ ++ class Sessions : public Connections{ ++ public: ++ Sessions(); ++ void reload(bool _master = false, bool reIssue = false); ++ std::string getSessId() const; ++ std::string getSessId(size_t idx) const; ++ void setSessId(std::string _sid); ++ void setSessId(std::string _sid, size_t idx); ++ bool sessIdExists(std::string _sid); ++ virtual void addFields(); ++ virtual void nullFields(); ++ virtual void fieldAccess(); ++ }; + }// namespace Comms +diff --git a/lib/defines.h b/lib/defines.h +index 10c4b9b1..203b75db 100644 +--- a/lib/defines.h ++++ b/lib/defines.h +@@ -196,11 +196,14 @@ static inline void show_stackframe(){} + #define TRACK_PAGE_RECORDSIZE 36 + + #define COMMS_STATISTICS "MstStat" +-#define COMMS_STATISTICS_INITSIZE 8 * 1024 * 1024 ++#define COMMS_STATISTICS_INITSIZE 16 * 1024 * 1024 + + #define COMMS_USERS "MstUser%s" //%s stream name + #define COMMS_USERS_INITSIZE 512 * 1024 + ++#define COMMS_SESSIONS "MstSession%s" ++#define COMMS_SESSIONS_INITSIZE 8 * 1024 * 1024 ++ + #define SEM_STATISTICS "/MstStat" + #define SEM_USERS "/MstUser%s" //%s stream name + +@@ -226,7 +229,9 @@ static inline void show_stackframe(){} + #define SEM_LIVE "/MstLIVE%s" //%s stream name + #define SEM_INPUT "/MstInpt%s" //%s stream name + #define SEM_TRACKLIST "/MstTRKS%s" //%s stream name ++#define SEM_SESSION "MstSess%s" + #define SEM_SESSCACHE "/MstSessCacheLock" ++#define SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID 14 + #define SHM_CAPA "MstCapa" + #define SHM_PROTO "MstProt" + #define SHM_PROXY "MstProx" +diff --git a/src/controller/controller.cpp b/src/controller/controller.cpp +index a0ff2ee8..9e17ca6b 100644 +--- a/src/controller/controller.cpp ++++ b/src/controller/controller.cpp +@@ -306,7 +306,6 @@ int main_loop(int argc, char **argv){ + if (Controller::Storage["config"].isMember("accesslog")){ + Controller::conf.getOption("accesslog", true)[0u] = Controller::Storage["config"]["accesslog"]; + } +- Controller::maxConnsPerIP = Controller::conf.getInteger("maxconnsperip"); + Controller::Storage["config"]["prometheus"] = Controller::conf.getString("prometheus"); + Controller::Storage["config"]["accesslog"] = Controller::conf.getString("accesslog"); + Controller::normalizeTrustedProxies(Controller::Storage["config"]["trustedproxy"]); +diff --git a/src/controller/controller_api.cpp b/src/controller/controller_api.cpp +index 4d94bb11..02491065 100644 +--- a/src/controller/controller_api.cpp ++++ b/src/controller/controller_api.cpp +@@ -594,6 +594,7 @@ void Controller::handleAPICommands(JSON::Value &Request, JSON::Value &Response){ + out["prometheus"] = in["prometheus"]; + Controller::prometheus = out["prometheus"].asStringRef(); + } ++ if (in.isMember("sessionMode")){out["sessionMode"] = in["sessionMode"];} + if (in.isMember("defaultStream")){out["defaultStream"] = in["defaultStream"];} + if (in.isMember("location") && in["location"].isObject()){ + out["location"]["lat"] = in["location"]["lat"].asDouble(); +diff --git a/src/controller/controller_statistics.cpp b/src/controller/controller_statistics.cpp +index c5b7f643..6e51f4ee 100644 +--- a/src/controller/controller_statistics.cpp ++++ b/src/controller/controller_statistics.cpp +@@ -15,6 +15,7 @@ + #include <mist/url.h> + #include <sys/statvfs.h> //for fstatvfs + #include <mist/triggers.h> ++#include <signal.h> + + #ifndef KILL_ON_EXIT + #define KILL_ON_EXIT false +@@ -30,7 +31,6 @@ + #define STAT_CLI_UP 64 + #define STAT_CLI_BPS_DOWN 128 + #define STAT_CLI_BPS_UP 256 +-#define STAT_CLI_CRC 512 + #define STAT_CLI_SESSID 1024 + #define STAT_CLI_PKTCOUNT 2048 + #define STAT_CLI_PKTLOST 4096 +@@ -46,59 +46,18 @@ + #define STAT_TOT_PERCRETRANS 64 + #define STAT_TOT_ALL 0xFF + +-#define COUNTABLE_BYTES 128 * 1024 +- +-std::map<Controller::sessIndex, Controller::statSession> Controller::sessions; ///< list of sessions that have statistics data available +-std::map<unsigned long, Controller::sessIndex> Controller::connToSession; ///< Map of socket IDs to session info. ++// Mapping of sessId -> session statistics ++std::map<std::string, Controller::statSession> sessions; + + std::map<std::string, Controller::triggerLog> Controller::triggerStats; ///< Holds prometheus stats for trigger executions + bool Controller::killOnExit = KILL_ON_EXIT; + tthread::mutex Controller::statsMutex; +-unsigned int Controller::maxConnsPerIP = 0; + uint64_t Controller::statDropoff = 0; + static uint64_t cpu_use = 0; + + char noBWCountMatches[1717]; + uint64_t bwLimit = 128 * 1024 * 1024; // gigabit default limit + +-/// Session cache shared memory page +-IPC::sharedPage *shmSessions = 0; +-/// Lock for the session cache shared memory page +-IPC::semaphore *cacheLock = 0; +- +-/// Convert bandwidth config into memory format +-void Controller::updateBandwidthConfig(){ +- size_t offset = 0; +- bwLimit = 128 * 1024 * 1024; // gigabit default limit +- memset(noBWCountMatches, 0, 1717); +- if (Storage.isMember("bandwidth")){ +- if (Storage["bandwidth"].isMember("limit")){bwLimit = Storage["bandwidth"]["limit"].asInt();} +- if (Storage["bandwidth"].isMember("exceptions")){ +- jsonForEach(Storage["bandwidth"]["exceptions"], j){ +- std::string newbins = Socket::getBinForms(j->asStringRef()); +- if (offset + newbins.size() < 1700){ +- memcpy(noBWCountMatches + offset, newbins.data(), newbins.size()); +- offset += newbins.size(); +- } +- } +- } +- } +- //Localhost is always excepted from counts +- { +- std::string newbins = Socket::getBinForms("::1"); +- if (offset + newbins.size() < 1700){ +- memcpy(noBWCountMatches + offset, newbins.data(), newbins.size()); +- offset += newbins.size(); +- } +- } +- { +- std::string newbins = Socket::getBinForms("127.0.0.1/8"); +- if (offset + newbins.size() < 1700){ +- memcpy(noBWCountMatches + offset, newbins.data(), newbins.size()); +- offset += newbins.size(); +- } +- } +-} + + // For server-wide totals. Local to this file only. + struct streamTotals{ +@@ -116,11 +75,30 @@ struct streamTotals{ + uint64_t packLoss; + uint64_t packRetrans; + }; ++ ++Comms::Sessions statComm; ++bool statCommActive = false; ++// Global server wide statistics ++static uint64_t servUpBytes = 0; ++static uint64_t servDownBytes = 0; ++static uint64_t servUpOtherBytes = 0; ++static uint64_t servDownOtherBytes = 0; ++static uint64_t servInputs = 0; ++static uint64_t servOutputs = 0; ++static uint64_t servViewers = 0; ++static uint64_t servSeconds = 0; ++static uint64_t servPackSent = 0; ++static uint64_t servPackLoss = 0; ++static uint64_t servPackRetrans = 0; ++// Total time watched for all sessions which are no longer active ++static uint64_t viewSecondsTotal = 0; ++// Mapping of streamName -> summary of stream-wide statistics + static std::map<std::string, struct streamTotals> streamStats; + +-static void createEmptyStatsIfNeeded(const std::string & strm){ +- if (streamStats.count(strm)){return;} +- streamTotals & sT = streamStats[strm]; ++// If sessId does not exist yet in streamStats, create and init an entry for it ++static void createEmptyStatsIfNeeded(const std::string & sessId){ ++ if (streamStats.count(sessId)){return;} ++ streamTotals & sT = streamStats[sessId]; + sT.upBytes = 0; + sT.downBytes = 0; + sT.inputs = 0; +@@ -136,68 +114,38 @@ static void createEmptyStatsIfNeeded(const std::string & strm){ + sT.packRetrans = 0; + } + +- +-static uint64_t servUpBytes = 0; +-static uint64_t servDownBytes = 0; +-static uint64_t servUpOtherBytes = 0; +-static uint64_t servDownOtherBytes = 0; +-static uint64_t servInputs = 0; +-static uint64_t servOutputs = 0; +-static uint64_t servViewers = 0; +-static uint64_t servSeconds = 0; +-static uint64_t servPackSent = 0; +-static uint64_t servPackLoss = 0; +-static uint64_t servPackRetrans = 0; +- +-Controller::sessIndex::sessIndex(){ +- crc = 0; +-} +- +-/// Initializes a sessIndex from a statistics object + index, converting binary format IP addresses +-/// into strings. This extracts the host, stream name, connector and crc field, ignoring everything +-/// else. +-Controller::sessIndex::sessIndex(const Comms::Statistics &statComm, size_t id){ +- Socket::hostBytesToStr(statComm.getHost(id).data(), 16, host); +- streamName = statComm.getStream(id); +- connector = statComm.getConnector(id); +- crc = statComm.getCRC(id); +- ID = statComm.getSessId(id); +-} +- +-std::string Controller::sessIndex::toStr(){ +- std::stringstream s; +- s << ID << "(" << host << " " << crc << " " << streamName << " " << connector << ")"; +- return s.str(); +-} +- +-bool Controller::sessIndex::operator==(const Controller::sessIndex &b) const{ +- return (host == b.host && crc == b.crc && streamName == b.streamName && connector == b.connector); +-} +- +-bool Controller::sessIndex::operator!=(const Controller::sessIndex &b) const{ +- return !(*this == b); +-} +- +-bool Controller::sessIndex::operator>(const Controller::sessIndex &b) const{ +- return host > b.host || +- (host == b.host && +- (crc > b.crc || (crc == b.crc && (streamName > b.streamName || +- (streamName == b.streamName && connector > b.connector))))); +-} +- +-bool Controller::sessIndex::operator<(const Controller::sessIndex &b) const{ +- return host < b.host || +- (host == b.host && +- (crc < b.crc || (crc == b.crc && (streamName < b.streamName || +- (streamName == b.streamName && connector < b.connector))))); +-} +- +-bool Controller::sessIndex::operator<=(const Controller::sessIndex &b) const{ +- return !(*this > b); +-} +- +-bool Controller::sessIndex::operator>=(const Controller::sessIndex &b) const{ +- return !(*this < b); ++/// Convert bandwidth config into memory format ++void Controller::updateBandwidthConfig(){ ++ size_t offset = 0; ++ bwLimit = 128 * 1024 * 1024; // gigabit default limit ++ memset(noBWCountMatches, 0, 1717); ++ if (Storage.isMember("bandwidth")){ ++ if (Storage["bandwidth"].isMember("limit")){bwLimit = Storage["bandwidth"]["limit"].asInt();} ++ if (Storage["bandwidth"].isMember("exceptions")){ ++ jsonForEach(Storage["bandwidth"]["exceptions"], j){ ++ std::string newbins = Socket::getBinForms(j->asStringRef()); ++ if (offset + newbins.size() < 1700){ ++ memcpy(noBWCountMatches + offset, newbins.data(), newbins.size()); ++ offset += newbins.size(); ++ } ++ } ++ } ++ } ++ //Localhost is always excepted from counts ++ { ++ std::string newbins = Socket::getBinForms("::1"); ++ if (offset + newbins.size() < 1700){ ++ memcpy(noBWCountMatches + offset, newbins.data(), newbins.size()); ++ offset += newbins.size(); ++ } ++ } ++ { ++ std::string newbins = Socket::getBinForms("127.0.0.1/8"); ++ if (offset + newbins.size() < 1700){ ++ memcpy(noBWCountMatches + offset, newbins.data(), newbins.size()); ++ offset += newbins.size(); ++ } ++ } + } + + /// This function is ran whenever a stream becomes active. +@@ -211,9 +159,6 @@ void Controller::streamStopped(std::string stream){ + INFO_MSG("Stream %s became inactive", stream.c_str()); + } + +-Comms::Statistics statComm; +-bool statCommActive = false; +- + /// Invalidates all current sessions for the given streamname + /// Updates the session cache, afterwards. + void Controller::sessions_invalidate(const std::string &streamname){ +@@ -221,18 +166,17 @@ void Controller::sessions_invalidate(const std::string &streamname){ + FAIL_MSG("In shutdown procedure - cannot invalidate sessions."); + return; + } +- unsigned int invalidated = 0; + unsigned int sessCount = 0; +- tthread::lock_guard<tthread::mutex> guard(statsMutex); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- if (it->first.streamName == streamname){ ++ // Find all matching streams in statComm ++ for (size_t i = 0; i < statComm.recordCount(); i++){ ++ if (statComm.getStatus(i) == COMM_STATUS_INVALID || (statComm.getStatus(i) & COMM_STATUS_DISCONNECT)){continue;} ++ if (statComm.getStream(i) == streamname){ + sessCount++; +- invalidated += it->second.invalidate(); ++ // Re-trigger USER_NEW trigger for this session ++ kill(statComm.getPid(i), SIGUSR1); + } + } +- Controller::writeSessionCache(); +- INFO_MSG("Invalidated %u connections in %u sessions for stream %s", invalidated, sessCount, +- streamname.c_str()); ++ INFO_MSG("Invalidated %u session(s) for stream %s", sessCount, streamname.c_str()); + } + + /// Shuts down all current sessions for the given streamname +@@ -256,18 +200,8 @@ void Controller::sessId_shutdown(const std::string &sessId){ + FAIL_MSG("In controller shutdown procedure - cannot shutdown sessions."); + return; + } +- unsigned int murdered = 0; +- unsigned int sessCount = 0; +- tthread::lock_guard<tthread::mutex> guard(statsMutex); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- if (it->first.ID == sessId){ +- sessCount++; +- murdered += it->second.kill(); +- break; +- } +- } +- Controller::writeSessionCache(); +- INFO_MSG("Shut down %u connections in %u session(s) for ID %s", murdered, sessCount, sessId.c_str()); ++ killConnections(sessId); ++ INFO_MSG("Shut down session with session ID %s", sessId.c_str()); + } + + /// Tags the given session +@@ -277,8 +211,8 @@ void Controller::sessId_tag(const std::string &sessId, const std::string &tag){ + return; + } + tthread::lock_guard<tthread::mutex> guard(statsMutex); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- if (it->first.ID == sessId){ ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ ++ if (it->first == sessId){ + it->second.tags.insert(tag); + return; + } +@@ -295,17 +229,15 @@ void Controller::tag_shutdown(const std::string &tag){ + FAIL_MSG("In controller shutdown procedure - cannot shutdown sessions."); + return; + } +- unsigned int murdered = 0; + unsigned int sessCount = 0; + tthread::lock_guard<tthread::mutex> guard(statsMutex); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ + if (it->second.tags.count(tag)){ + sessCount++; +- murdered += it->second.kill(); ++ killConnections(it->first); + } + } +- Controller::writeSessionCache(); +- INFO_MSG("Shut down %u connections in %u session(s) for tag %s", murdered, sessCount, tag.c_str()); ++ INFO_MSG("Shut down %u session(s) for tag %s", sessCount, tag.c_str()); + } + + /// Shuts down all current sessions for the given streamname +@@ -315,48 +247,23 @@ void Controller::sessions_shutdown(const std::string &streamname, const std::str + FAIL_MSG("In controller shutdown procedure - cannot shutdown sessions."); + return; + } +- unsigned int murdered = 0; + unsigned int sessCount = 0; + tthread::lock_guard<tthread::mutex> guard(statsMutex); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- if ((!streamname.size() || it->first.streamName == streamname) && +- (!protocol.size() || it->first.connector == protocol)){ ++ // Find all matching streams in statComm and get their sessId ++ for (size_t i = 0; i < statComm.recordCount(); i++){ ++ if (statComm.getStatus(i) == COMM_STATUS_INVALID || (statComm.getStatus(i) & COMM_STATUS_DISCONNECT)){continue;} ++ if ((!streamname.size() || statComm.getStream(i) == streamname) && ++ (!protocol.size() || statComm.hasConnector(i, protocol))){ ++ uint32_t pid = statComm.getPid(i); + sessCount++; +- murdered += it->second.kill(); +- } +- } +- Controller::writeSessionCache(); +- INFO_MSG("Shut down %u connections in %u sessions for stream %s/%s", murdered, sessCount, +- streamname.c_str(), protocol.c_str()); +-} +- +-/// Writes the session cache to shared memory. +-/// Assumes the config mutex, stats mutex and session cache semaphore are already locked. +-/// Does nothing if the session cache could not be initialized on the first try +-/// Does no error checking after first open attempt (fails silently)! +-void Controller::writeSessionCache(){ +- uint32_t shmOffset = 0; +- if (shmSessions && shmSessions->mapped){ +- if (cacheLock){cacheLock->wait(16);} +- if (sessions.size()){ +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- if (it->second.hasData()){ +- // store an entry in the shmSessions page, if it fits +- if (it->second.sync > 2 && shmOffset + SHM_SESSIONS_ITEM < SHM_SESSIONS_SIZE){ +- *((uint32_t *)(shmSessions->mapped + shmOffset)) = it->first.crc; +- strncpy(shmSessions->mapped + shmOffset + 4, it->first.streamName.c_str(), 100); +- strncpy(shmSessions->mapped + shmOffset + 104, it->first.connector.c_str(), 20); +- strncpy(shmSessions->mapped + shmOffset + 124, it->first.host.c_str(), 40); +- shmSessions->mapped[shmOffset + 164] = it->second.sync; +- shmOffset += SHM_SESSIONS_ITEM; +- } +- } ++ if (pid > 1){ ++ Util::Procs::Stop(pid); ++ INFO_MSG("Killing PID %" PRIu32, pid); + } + } +- // set a final shmSessions entry to all zeroes +- memset(shmSessions->mapped + shmOffset, 0, SHM_SESSIONS_ITEM); +- if (cacheLock){cacheLock->post(16);} + } ++ INFO_MSG("Shut down %u sessions for stream %s/%s", sessCount, ++ streamname.c_str(), protocol.c_str()); + } + + /// This function runs as a thread and roughly once per second retrieves +@@ -366,14 +273,6 @@ void Controller::SharedMemStats(void *config){ + HIGH_MSG("Starting stats thread"); + statComm.reload(true); + statCommActive = true; +- shmSessions = new IPC::sharedPage(SHM_SESSIONS, SHM_SESSIONS_SIZE, false, false); +- if (!shmSessions || !shmSessions->mapped){ +- if (shmSessions){delete shmSessions;} +- shmSessions = new IPC::sharedPage(SHM_SESSIONS, SHM_SESSIONS_SIZE, true); +- } +- cacheLock = new IPC::semaphore(SEM_SESSCACHE, O_CREAT | O_RDWR, ACCESSPERMS, 16); +- cacheLock->unlink(); +- cacheLock->open(SEM_SESSCACHE, O_CREAT | O_RDWR, ACCESSPERMS, 16); + std::set<std::string> inactiveStreams; + Controller::initState(); + bool shiftWrites = true; +@@ -401,7 +300,6 @@ void Controller::SharedMemStats(void *config){ + } + } + { +- + tthread::lock_guard<tthread::mutex> guard(Controller::configMutex); + tthread::lock_guard<tthread::mutex> guard2(statsMutex); + // parse current users +@@ -429,29 +327,47 @@ void Controller::SharedMemStats(void *config){ + it->second.packRetrans = 0; + } + } +- // wipe old statistics ++ unsigned int tOut = Util::bootSecs() - STATS_DELAY; ++ unsigned int tIn = Util::bootSecs() - STATS_INPUT_DELAY; ++ if (streamStats.size()){ ++ for (std::map<std::string, struct streamTotals>::iterator it = streamStats.begin(); ++ it != streamStats.end(); ++it){ ++ it->second.currViews = 0; ++ it->second.currIns = 0; ++ it->second.currOuts = 0; ++ } ++ } ++ // wipe old statistics and set session type counters + if (sessions.size()){ +- std::list<sessIndex> mustWipe; ++ std::list<std::string> mustWipe; + uint64_t cutOffPoint = Util::bootSecs() - STAT_CUTOFF; +- uint64_t disconnectPointIn = Util::bootSecs() - STATS_INPUT_DELAY; +- uint64_t disconnectPointOut = Util::bootSecs() - STATS_DELAY; +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- uint64_t dPoint = it->second.getSessType() == SESS_INPUT ? disconnectPointIn : disconnectPointOut; +- if (it->second.sync == 100){ +- // Denied entries are connection-entry-wiped as soon as they become boring +- it->second.wipeOld(dPoint); +- }else{ +- // Normal entries are summarized after STAT_CUTOFF seconds +- it->second.wipeOld(cutOffPoint); +- } ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ + // This part handles ending sessions, keeping them in cache for now +- if (it->second.isTracked() && !it->second.isConnected() && it->second.getEnd() < dPoint){ +- it->second.dropSession(it->first); +- } +- // This part handles wiping from the session cache +- if (!it->second.hasData()){ +- it->second.dropSession(it->first); // End the session, just in case it wasn't yet ++ if (it->second.getEnd() < cutOffPoint && it->second.newestDataPoint() < cutOffPoint){ ++ viewSecondsTotal += it->second.getConnTime(); + mustWipe.push_back(it->first); ++ // Don't count this session as a viewer ++ continue; ++ } ++ // Recount input, output and viewer type sessions ++ switch (it->second.getSessType()){ ++ case SESS_UNSET: break; ++ case SESS_VIEWER: ++ if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){ ++ streamStats[it->first].currViews++; ++ } ++ servSeconds += it->second.getConnTime(); ++ break; ++ case SESS_INPUT: ++ if (it->second.hasDataFor(tIn) && it->second.isViewerOn(tIn)){ ++ streamStats[it->first].currIns++; ++ } ++ break; ++ case SESS_OUTPUT: ++ if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){ ++ streamStats[it->first].currOuts++; ++ } ++ break; + } + } + while (mustWipe.size()){ +@@ -513,7 +429,6 @@ void Controller::SharedMemStats(void *config){ + shiftWrites = true; + } + /*LTS-START*/ +- Controller::writeSessionCache(); + Controller::checkServerLimits(); + /*LTS-END*/ + } +@@ -523,7 +438,6 @@ void Controller::SharedMemStats(void *config){ + HIGH_MSG("Stopping stats thread"); + if (Util::Config::is_restarting){ + statComm.setMaster(false); +- shmSessions->master = false; + }else{/*LTS-START*/ + if (Controller::killOnExit){ + WARN_MSG("Killing all connected clients to force full shutdown"); +@@ -532,10 +446,6 @@ void Controller::SharedMemStats(void *config){ + /*LTS-END*/ + } + Controller::deinitState(Util::Config::is_restarting); +- delete shmSessions; +- shmSessions = 0; +- delete cacheLock; +- cacheLock = 0; + } + + /// Gets a complete list of all streams currently in active state, with optional prefix matching +@@ -559,97 +469,53 @@ std::set<std::string> Controller::getActiveStreams(const std::string &prefix){ + return ret; + } + +-/// Forces a re-sync of the session +-/// Assumes the session cache will be updated separately - may not work correctly if this is forgotten! +-uint32_t Controller::statSession::invalidate(){ +- uint32_t ret = 0; +- sync = 1; +- if (curConns.size() && statCommActive){ +- for (std::map<uint64_t, statStorage>::iterator jt = curConns.begin(); jt != curConns.end(); ++jt){ +- if (statComm.getStatus(jt->first) != COMM_STATUS_INVALID){ +- statComm.setSync(2, jt->first); +- ret++; +- } +- } +- } +- return ret; +-} +- +-/// Kills all active connections, sets the session state to denied (sync=100). ++/// Kills all connection of a given session + /// Assumes the session cache will be updated separately - may not work correctly if this is forgotten! +-uint32_t Controller::statSession::kill(){ +- uint32_t ret = 0; +- sync = 100; +- if (curConns.size() && statCommActive){ +- for (std::map<uint64_t, statStorage>::iterator jt = curConns.begin(); jt != curConns.end(); ++jt){ +- if (statComm.getStatus(jt->first) != COMM_STATUS_INVALID){ +- statComm.setSync(100, jt->first); +- uint32_t pid = statComm.getPid(jt->first); ++void Controller::killConnections(std::string sessId){ ++ if (statCommActive){ ++ // Find a matching stream in statComm with a matching sessID and kill it ++ for (size_t i = 0; i < statComm.recordCount(); i++){ ++ if (statComm.getStatus(i) == COMM_STATUS_INVALID || (statComm.getStatus(i) & COMM_STATUS_DISCONNECT)){continue;} ++ if (statComm.getSessId(i) == sessId){ ++ uint32_t pid = statComm.getPid(i); + if (pid > 1){ + Util::Procs::Stop(pid); + INFO_MSG("Killing PID %" PRIu32, pid); + } +- ret++; + } + } + } +- return ret; + } + + /// Updates the given active connection with new stats data. +-void Controller::statSession::update(uint64_t index, Comms::Statistics &statComm){ +- std::string myHost; +- Socket::hostBytesToStr(statComm.getHost(index).data(), 16, myHost); +- std::string myStream = statComm.getStream(index); +- std::string myConnector = statComm.getConnector(index); +- // update the sync byte: 0 = requesting fill, 2 = requesting refill, 1 = needs checking, > 2 = +- // state known (100=denied, 10=accepted) +- if (!statComm.getSync(index)){ +- sessIndex tmpidx(statComm, index); +- // if we have a maximum connection count per IP, enforce it +- if (maxConnsPerIP && !statComm.getSync(index)){ +- unsigned int currConns = 1; +- long long shortly = Util::bootSecs(); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- +- if (&it->second != this && it->first.host == myHost && +- (it->second.hasDataFor(shortly - STATS_DELAY) || it->second.hasDataFor(shortly) || +- it->second.hasDataFor(shortly - 1) || it->second.hasDataFor(shortly - 2) || +- it->second.hasDataFor(shortly - 3) || it->second.hasDataFor(shortly - 4) || +- it->second.hasDataFor(shortly - 5)) && +- ++currConns > maxConnsPerIP){ +- break; +- } +- } +- if (currConns > maxConnsPerIP){ +- WARN_MSG("Disconnecting session from %s: exceeds max connection count of %u", myHost.c_str(), maxConnsPerIP); +- statComm.setSync(100, index); +- } +- } +- if (statComm.getSync(index) != 100){ +- // only set the sync if this is the first connection in the list +- // we also catch the case that there are no connections, which is an error-state +- if (!sessions[tmpidx].curConns.size() || sessions[tmpidx].curConns.begin()->first == index){ +- MEDIUM_MSG("Requesting sync to %u for %s, %s, %s, %" PRIu32, sync, myStream.c_str(), +- myConnector.c_str(), myHost.c_str(), statComm.getCRC(index) & 0xFFFFFFFFu); +- statComm.setSync(sync, index); +- } +- // and, always set the sync if it is > 2 +- if (sync > 2){ +- MEDIUM_MSG("Setting sync to %u for %s, %s, %s, %" PRIu32, sync, myStream.c_str(), +- myConnector.c_str(), myHost.c_str(), statComm.getCRC(index) & 0xFFFFFFFFu); +- statComm.setSync(sync, index); +- } ++void Controller::statSession::update(uint64_t index, Comms::Sessions &statComm){ ++ if (host == ""){ ++ Socket::hostBytesToStr(statComm.getHost(index).data(), 16, host); ++ } ++ if (streamName == ""){ ++ streamName = statComm.getStream(index); ++ } ++ if (curConnector == ""){ ++ curConnector = statComm.getConnector(index); ++ } ++ if (sessId == ""){ ++ sessId = statComm.getSessId(index); ++ } ++ // Export tags to session ++ if (tags.size()){ ++ std::stringstream tagStream; ++ for (std::set<std::string>::iterator it = tags.begin(); it != tags.end(); ++it){ ++ tagStream << "[" << *it << "]"; + } +- }else{ +- if (sync < 2 && statComm.getSync(index) > 2){sync = statComm.getSync(index);} ++ statComm.setTags(tagStream.str(), index); + } ++ + long long prevDown = getDown(); + long long prevUp = getUp(); + uint64_t prevPktSent = getPktCount(); + uint64_t prevPktLost = getPktLost(); + uint64_t prevPktRetrans = getPktRetransmit(); +- curConns[index].update(statComm, index); ++ curData.update(statComm, index); + // store timestamp of first received data, if older + if (firstSec > statComm.getNow(index)){firstSec = statComm.getNow(index);} + uint64_t secIncr = 0; +@@ -671,7 +537,7 @@ void Controller::statSession::update(uint64_t index, Comms::Statistics &statComm + uint64_t currPktRetrans = getPktRetransmit(); + if (currUp - prevUp < 0 || currDown - prevDown < 0){ + INFO_MSG("Negative data usage! %lldu/%lldd (u%lld->%lld) in %s over %s, #%" PRIu64, currUp - prevUp, +- currDown - prevDown, prevUp, currUp, myStream.c_str(), myConnector.c_str(), index); ++ currDown - prevDown, prevUp, currUp, streamName.c_str(), curConnector.c_str(), index); + }else{ + if (!noBWCount){ + size_t bwMatchOffset = 0; +@@ -701,56 +567,39 @@ void Controller::statSession::update(uint64_t index, Comms::Statistics &statComm + servPackRetrans += currPktRetrans - prevPktRetrans; + } + } +- if (currDown + currUp >= COUNTABLE_BYTES){ +- if (sessionType == SESS_UNSET){ +- if (myConnector.size() >= 5 && myConnector.substr(0, 5) == "INPUT"){ +- ++servInputs; +- createEmptyStatsIfNeeded(myStream); +- streamStats[myStream].inputs++; +- streamStats[myStream].currIns++; +- sessionType = SESS_INPUT; +- }else if (myConnector.size() >= 6 && myConnector.substr(0, 6) == "OUTPUT"){ +- ++servOutputs; +- createEmptyStatsIfNeeded(myStream); +- streamStats[myStream].outputs++; +- streamStats[myStream].currOuts++; +- sessionType = SESS_OUTPUT; +- }else{ +- ++servViewers; +- createEmptyStatsIfNeeded(myStream); +- streamStats[myStream].viewers++; +- streamStats[myStream].currViews++; +- sessionType = SESS_VIEWER; +- } ++ if (sessionType == SESS_UNSET){ ++ if (curConnector.size() >= 5 && curConnector.substr(0, 5) == "INPUT"){ ++ ++servInputs; ++ createEmptyStatsIfNeeded(streamName); ++ streamStats[streamName].inputs++; ++ streamStats[streamName].currIns++; ++ sessionType = SESS_INPUT; ++ }else if (curConnector.size() >= 6 && curConnector.substr(0, 6) == "OUTPUT"){ ++ ++servOutputs; ++ createEmptyStatsIfNeeded(streamName); ++ streamStats[streamName].outputs++; ++ streamStats[streamName].currOuts++; ++ sessionType = SESS_OUTPUT; ++ }else{ ++ ++servViewers; ++ createEmptyStatsIfNeeded(streamName); ++ streamStats[streamName].viewers++; ++ streamStats[streamName].currViews++; ++ sessionType = SESS_VIEWER; + } +- // If previous < COUNTABLE_BYTES, we haven't counted any data so far. +- // We need to count all the data in that case, otherwise we only count the difference. +- if (noBWCount != 2){ //only count connections that are countable +- if (prevUp + prevDown < COUNTABLE_BYTES){ +- if (!myStream.size() || myStream[0] == 0){ +- if (streamStats.count(myStream)){streamStats.erase(myStream);} +- }else{ +- createEmptyStatsIfNeeded(myStream); +- streamStats[myStream].upBytes += currUp; +- streamStats[myStream].downBytes += currDown; +- streamStats[myStream].packSent += currPktSent; +- streamStats[myStream].packLoss += currPktLost; +- streamStats[myStream].packRetrans += currPktRetrans; +- if (sessionType == SESS_VIEWER){streamStats[myStream].viewSeconds += lastSec - firstSec;} +- } +- }else{ +- if (!myStream.size() || myStream[0] == 0){ +- if (streamStats.count(myStream)){streamStats.erase(myStream);} +- }else{ +- createEmptyStatsIfNeeded(myStream); +- streamStats[myStream].upBytes += currUp - prevUp; +- streamStats[myStream].downBytes += currDown - prevDown; +- streamStats[myStream].packSent += currPktSent - prevPktSent; +- streamStats[myStream].packLoss += currPktLost - prevPktLost; +- streamStats[myStream].packRetrans += currPktRetrans - prevPktRetrans; +- if (sessionType == SESS_VIEWER){streamStats[myStream].viewSeconds += secIncr;} +- } +- } ++ } ++ // Only count connections that are countable ++ if (noBWCount != 2){ ++ if (!streamName.size() || streamName[0] == 0){ ++ if (streamStats.count(streamName)){streamStats.erase(streamName);} ++ }else{ ++ createEmptyStatsIfNeeded(streamName); ++ streamStats[streamName].upBytes += currUp - prevUp; ++ streamStats[streamName].downBytes += currDown - prevDown; ++ streamStats[streamName].packSent += currPktSent - prevPktSent; ++ streamStats[streamName].packLoss += currPktLost - prevPktLost; ++ streamStats[streamName].packRetrans += currPktRetrans - prevPktRetrans; ++ if (sessionType == SESS_VIEWER){streamStats[streamName].viewSeconds += secIncr;} + } + } + } +@@ -759,53 +608,19 @@ Controller::sessType Controller::statSession::getSessType(){ + return sessionType; + } + +-/// Archives connection log entries older than the given cutOff point. +-void Controller::statSession::wipeOld(uint64_t cutOff){ +- if (firstSec > cutOff){return;} +- firstSec = 0xFFFFFFFFFFFFFFFFull; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- while (it->log.size() && it->log.begin()->first < cutOff){ +- if (it->log.size() == 1){ +- wipedDown += it->log.begin()->second.down; +- wipedUp += it->log.begin()->second.up; +- wipedPktCount += it->log.begin()->second.pktCount; +- wipedPktLost += it->log.begin()->second.pktLost; +- wipedPktRetransmit += it->log.begin()->second.pktRetransmit; +- } +- it->log.erase(it->log.begin()); +- } +- if (it->log.size()){ +- if (firstSec > it->log.begin()->first){firstSec = it->log.begin()->first;} +- } +- } +- while (oldConns.size() && !oldConns.begin()->log.size()){oldConns.pop_front();} +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- while (it->second.log.size() > 1 && it->second.log.begin()->first < cutOff){ +- it->second.log.erase(it->second.log.begin()); +- } +- if (it->second.log.size()){ +- if (firstSec > it->second.log.begin()->first){firstSec = it->second.log.begin()->first;} +- } +- } +- } +-} +- +-void Controller::statSession::dropSession(const Controller::sessIndex &index){ +- if (!tracked || curConns.size()){return;} ++Controller::statSession::~statSession(){ ++ if (!tracked){return;} + switch (sessionType){ +- case SESS_INPUT: +- if (streamStats.count(index.streamName) && streamStats[index.streamName].currIns){streamStats[index.streamName].currIns--;} +- break; +- case SESS_OUTPUT: +- if (streamStats.count(index.streamName) && streamStats[index.streamName].currOuts){streamStats[index.streamName].currOuts--;} +- break; +- case SESS_VIEWER: +- if (streamStats.count(index.streamName) && streamStats[index.streamName].currViews){streamStats[index.streamName].currViews--;} +- break; +- default: break; ++ case SESS_INPUT: ++ if (streamStats.count(streamName) && streamStats[streamName].currIns){streamStats[streamName].currIns--;} ++ break; ++ case SESS_OUTPUT: ++ if (streamStats.count(streamName) && streamStats[streamName].currOuts){streamStats[streamName].currOuts--;} ++ break; ++ case SESS_VIEWER: ++ if (streamStats.count(streamName) && streamStats[streamName].currViews){streamStats[streamName].currViews--;} ++ break; ++ default: break; + } + uint64_t duration = lastSec - firstActive; + if (duration < 1){duration = 1;} +@@ -815,13 +630,13 @@ void Controller::statSession::dropSession(const Controller::sessIndex &index){ + tagStream << "[" << *it << "]"; + } + } +- Controller::logAccess(index.ID, index.streamName, index.connector, index.host, duration, getUp(), ++ Controller::logAccess(sessId, streamName, curConnector, host, duration, getUp(), + getDown(), tagStream.str()); + if (Controller::accesslog.size()){ + if (Controller::accesslog == "LOG"){ + std::stringstream accessStr; +- accessStr << "Session <" << index.ID << "> " << index.streamName << " (" << index.connector +- << ") from " << index.host << " ended after " << duration << "s, avg " ++ accessStr << "Session <" << sessId << "> " << streamName << " (" << curConnector ++ << ") from " << host << " ended after " << duration << "s, avg " + << getUp() / duration / 1024 << "KB/s up " << getDown() / duration / 1024 << "KB/s down."; + if (tags.size()){accessStr << " Tags: " << tagStream.str();} + Controller::Log("ACCS", accessStr.str()); +@@ -845,8 +660,8 @@ void Controller::statSession::dropSession(const Controller::sessIndex &index){ + time(&rawtime); + timeinfo = localtime_r(&rawtime, &tmptime); + strftime(buffer, 100, "%F %H:%M:%S", timeinfo); +- accLogFile << buffer << ", " << index.ID << ", " << index.streamName << ", " +- << index.connector << ", " << index.host << ", " << duration << ", " ++ accLogFile << buffer << ", " << sessId << ", " << streamName << ", " ++ << curConnector << ", " << host << ", " << duration << ", " + << getUp() / duration / 1024 << ", " << getDown() / duration / 1024 << ", "; + if (tags.size()){accLogFile << tagStream.str();} + accLogFile << std::endl; +@@ -857,77 +672,21 @@ void Controller::statSession::dropSession(const Controller::sessIndex &index){ + firstActive = 0; + firstSec = 0xFFFFFFFFFFFFFFFFull; + lastSec = 0; +- wipedUp = 0; +- wipedDown = 0; +- wipedPktCount = 0; +- wipedPktLost = 0; +- wipedPktRetransmit = 0; +- oldConns.clear(); + sessionType = SESS_UNSET; + } + +-/// Archives the given connection. +-void Controller::statSession::finish(uint64_t index){ +- oldConns.push_back(curConns[index]); +- curConns.erase(index); +-} +- + /// Constructs an empty session + Controller::statSession::statSession(){ + firstActive = 0; + tracked = false; + firstSec = 0xFFFFFFFFFFFFFFFFull; + lastSec = 0; +- sync = 1; +- wipedUp = 0; +- wipedDown = 0; +- wipedPktCount = 0; +- wipedPktLost = 0; +- wipedPktRetransmit = 0; + sessionType = SESS_UNSET; + noBWCount = 0; +-} +- +-/// Moves the given connection to the given session +-void Controller::statSession::switchOverTo(statSession &newSess, uint64_t index){ +- // add to the given session first +- newSess.curConns[index] = curConns[index]; +- // if this connection has data, update firstSec/lastSec if needed +- if (curConns[index].log.size()){ +- if (newSess.firstSec > curConns[index].log.begin()->first){ +- newSess.firstSec = curConns[index].log.begin()->first; +- } +- if (newSess.lastSec < curConns[index].log.rbegin()->first){ +- newSess.lastSec = curConns[index].log.rbegin()->first; +- } +- } +- // remove from current session +- curConns.erase(index); +- // if there was any data, recalculate this session's firstSec and lastSec. +- if (newSess.curConns[index].log.size()){ +- firstSec = 0xFFFFFFFFFFFFFFFFull; +- lastSec = 0; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){ +- if (firstSec > it->log.begin()->first){firstSec = it->log.begin()->first;} +- if (lastSec < it->log.rbegin()->first){lastSec = it->log.rbegin()->first;} +- } +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.log.size()){ +- if (firstSec > it->second.log.begin()->first){ +- firstSec = it->second.log.begin()->first; +- } +- if (lastSec < it->second.log.rbegin()->first){ +- lastSec = it->second.log.rbegin()->first; +- } +- } +- } +- } +- } ++ streamName = ""; ++ host = ""; ++ curConnector = ""; ++ sessId = ""; + } + + /// Returns the first measured timestamp in this session. +@@ -944,39 +703,34 @@ uint64_t Controller::statSession::getEnd(){ + bool Controller::statSession::hasDataFor(uint64_t t){ + if (lastSec < t){return false;} + if (firstSec > t){return false;} +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){return true;} +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){return true;} +- } +- } +- return false; +-} +- +-/// Returns true if there is any data for this session. +-bool Controller::statSession::hasData(){ +- if (!firstSec && !lastSec){return false;} +- if (curConns.size()){return true;} +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){return true;} +- } +- } ++ if (curData.hasDataFor(t)){return true;} + return false; + } + + /// Returns true if this session should count as a viewer on the given timestamp. + bool Controller::statSession::isViewerOn(uint64_t t){ +- return getUp(t) + getDown(t) > COUNTABLE_BYTES; ++ return getUp(t) + getDown(t); ++} ++ ++std::string Controller::statSession::getStreamName(){ ++ return streamName; ++} ++ ++std::string Controller::statSession::getHost(){ ++ return host; ++} ++ ++std::string Controller::statSession::getSessId(){ ++ return sessId; ++} ++ ++std::string Controller::statSession::getCurrentProtocols(){ ++ return curConnector; + } + + /// Returns true if this session should be considered connected +-bool Controller::statSession::isConnected(){ +- return curConns.size(); ++uint64_t Controller::statSession::newestDataPoint(){ ++ return lastSec; + } + + /// Returns true if this session has started (tracked == true) but not yet ended (log entry written) +@@ -986,188 +740,103 @@ bool Controller::statSession::isTracked(){ + + /// Returns the cumulative connected time for this session at timestamp t. + uint64_t Controller::statSession::getConnTime(uint64_t t){ +- uint64_t retVal = 0; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){retVal += it->getDataFor(t).time;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).time; + } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){retVal += it->second.getDataFor(t).time;} +- } ++ return 0; ++} ++ ++/// Returns the cumulative connected time for this session. ++uint64_t Controller::statSession::getConnTime(){ ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.time; + } +- return retVal; ++ return 0; + } + + /// Returns the last requested media timestamp for this session at timestamp t. + uint64_t Controller::statSession::getLastSecond(uint64_t t){ +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){return it->second.getDataFor(t).lastSecond;} +- } +- } +- if (oldConns.size()){ +- for (std::deque<statStorage>::reverse_iterator it = oldConns.rbegin(); it != oldConns.rend(); ++it){ +- if (it->hasDataFor(t)){return it->getDataFor(t).lastSecond;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).lastSecond; + } + return 0; + } + + /// Returns the cumulative downloaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getDown(uint64_t t){ +- uint64_t retVal = wipedDown; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){retVal += it->getDataFor(t).down;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).down; + } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){retVal += it->second.getDataFor(t).down;} +- } +- } +- return retVal; ++ return 0; + } + + /// Returns the cumulative uploaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getUp(uint64_t t){ +- uint64_t retVal = wipedUp; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){retVal += it->getDataFor(t).up;} +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){retVal += it->second.getDataFor(t).up;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).up; + } +- return retVal; ++ return 0; + } + + /// Returns the cumulative downloaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getDown(){ +- uint64_t retVal = wipedDown; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){retVal += it->log.rbegin()->second.down;} +- } ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.down; + } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.log.size()){retVal += it->second.log.rbegin()->second.down;} +- } +- } +- return retVal; ++ return 0; + } + + /// Returns the cumulative uploaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getUp(){ +- uint64_t retVal = wipedUp; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){retVal += it->log.rbegin()->second.up;} +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.log.size()){retVal += it->second.log.rbegin()->second.up;} +- } ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.up; + } +- return retVal; ++ return 0; + } + + uint64_t Controller::statSession::getPktCount(uint64_t t){ +- uint64_t retVal = wipedPktCount; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){retVal += it->getDataFor(t).pktCount;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).pktCount; + } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){retVal += it->second.getDataFor(t).pktCount;} +- } +- } +- return retVal; ++ return 0; + } + + /// Returns the cumulative uploaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getPktCount(){ +- uint64_t retVal = wipedPktCount; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){retVal += it->log.rbegin()->second.pktCount;} +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.log.size()){retVal += it->second.log.rbegin()->second.pktCount;} +- } ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.pktCount; + } +- return retVal; ++ return 0; + } ++ + uint64_t Controller::statSession::getPktLost(uint64_t t){ +- uint64_t retVal = wipedPktLost; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){retVal += it->getDataFor(t).pktLost;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).pktLost; + } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){retVal += it->second.getDataFor(t).pktLost;} +- } +- } +- return retVal; ++ return 0; + } + + /// Returns the cumulative uploaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getPktLost(){ +- uint64_t retVal = wipedPktLost; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){retVal += it->log.rbegin()->second.pktLost;} +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.log.size()){retVal += it->second.log.rbegin()->second.pktLost;} +- } ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.pktLost; + } +- return retVal; ++ return 0; + } ++ + uint64_t Controller::statSession::getPktRetransmit(uint64_t t){ +- uint64_t retVal = wipedPktRetransmit; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->hasDataFor(t)){retVal += it->getDataFor(t).pktRetransmit;} +- } ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).pktRetransmit; + } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.hasDataFor(t)){retVal += it->second.getDataFor(t).pktRetransmit;} +- } +- } +- return retVal; ++ return 0; + } + + /// Returns the cumulative uploaded bytes for this session at timestamp t. + uint64_t Controller::statSession::getPktRetransmit(){ +- uint64_t retVal = wipedPktRetransmit; +- if (oldConns.size()){ +- for (std::deque<statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); ++it){ +- if (it->log.size()){retVal += it->log.rbegin()->second.pktRetransmit;} +- } +- } +- if (curConns.size()){ +- for (std::map<uint64_t, statStorage>::iterator it = curConns.begin(); it != curConns.end(); ++it){ +- if (it->second.log.size()){retVal += it->second.log.rbegin()->second.pktRetransmit;} +- } ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.pktRetransmit; + } +- return retVal; ++ return 0; + } + + /// Returns the cumulative downloaded bytes per second for this session at timestamp t. +@@ -1207,6 +876,7 @@ Controller::statLog &Controller::statStorage::getDataFor(unsigned long long t){ + empty.pktCount = 0; + empty.pktLost = 0; + empty.pktRetransmit = 0; ++ empty.connectors = ""; + return empty; + } + std::map<unsigned long long, statLog>::iterator it = log.upper_bound(t); +@@ -1216,7 +886,7 @@ Controller::statLog &Controller::statStorage::getDataFor(unsigned long long t){ + + /// This function is called by parseStatistics. + /// It updates the internally saved statistics data. +-void Controller::statStorage::update(Comms::Statistics &statComm, size_t index){ ++void Controller::statStorage::update(Comms::Sessions &statComm, size_t index){ + statLog tmp; + tmp.time = statComm.getTime(index); + tmp.lastSecond = statComm.getLastSecond(index); +@@ -1225,56 +895,58 @@ void Controller::statStorage::update(Comms::Statistics &statComm, size_t index){ + tmp.pktCount = statComm.getPacketCount(index); + tmp.pktLost = statComm.getPacketLostCount(index); + tmp.pktRetransmit = statComm.getPacketRetransmitCount(index); ++ tmp.connectors = statComm.getConnector(index); + log[statComm.getNow(index)] = tmp; +- // wipe data older than approx. STAT_CUTOFF seconds +- /// \todo Remove least interesting data first. +- if (log.size() > STAT_CUTOFF){log.erase(log.begin());} ++ // wipe data older than STAT_CUTOFF seconds ++ while (log.size() && log.begin()->first < Util::bootSecs() - STAT_CUTOFF){log.erase(log.begin());} + } + + void Controller::statLeadIn(){ + statDropoff = Util::bootSecs() - 3; + } +-void Controller::statOnActive(size_t id){ +- // calculate the current session index, store as idx. +- sessIndex idx(statComm, id); + ++void Controller::statOnActive(size_t id){ + if (statComm.getNow(id) >= statDropoff){ +- // if the connection was already indexed and it has changed, move it +- if (connToSession.count(id) && connToSession[id] != idx){ +- if (sessions[connToSession[id]].getSessType() != SESS_UNSET){ +- INFO_MSG("Switching connection %zu from active session %s over to %s", id, +- connToSession[id].toStr().c_str(), idx.toStr().c_str()); +- }else{ +- INFO_MSG("Switching connection %zu from inactive session %s over to %s", id, +- connToSession[id].toStr().c_str(), idx.toStr().c_str()); +- } +- sessions[connToSession[id]].switchOverTo(sessions[idx], id); +- // Destroy this session without calling dropSession, because it was merged into another. What session? We never made it. Stop asking hard questions. Go, shoo. *sprays water* +- if (!sessions[connToSession[id]].hasData()){sessions.erase(connToSession[id]);} +- } +- if (!connToSession.count(id)){ +- INSANE_MSG("New connection: %zu as %s", id, idx.toStr().c_str()); +- } +- // store the index for later comparison +- connToSession[id] = idx; + // update the session with the latest data +- sessions[idx].update(id, statComm); ++ sessions[statComm.getSessId(id)].update(id, statComm); + } + } ++ + void Controller::statOnDisconnect(size_t id){ +- sessIndex idx(statComm, id); +- INSANE_MSG("Ended connection: %zu as %s", id, idx.toStr().c_str()); +- sessions[idx].finish(id); +- connToSession.erase(id); ++ // Check to see if cleanup is required (when a Session binary fails) ++ const std::string thisSessionId = statComm.getSessId(id); ++ // Try to lock to see if the session crashed during boot ++ IPC::semaphore sessionLock; ++ char semName[NAME_BUFFER_SIZE]; ++ snprintf(semName, NAME_BUFFER_SIZE, SEM_SESSION, thisSessionId.c_str()); ++ sessionLock.open(semName, O_CREAT | O_RDWR, ACCESSPERMS, 1); ++ if (!sessionLock.tryWaitOneSecond()){ ++ // Session likely crashed during boot. Remove the session lock which was created on bootup of the session ++ sessionLock.unlink(); ++ }else if (!statComm.sessIdExists(thisSessionId)){ ++ // There is no running process managing this session, so check if the data page still exists ++ IPC::sharedPage dataPage; ++ char userPageName[NAME_BUFFER_SIZE]; ++ snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_SESSIONS, thisSessionId.c_str()); ++ dataPage.init(userPageName, 1, false, false); ++ if(dataPage){ ++ // Session likely crashed while it was running ++ dataPage.init(userPageName, 1, true); ++ FAIL_MSG("Session '%s' got canceled unexpectedly. Hoovering up the left overs...", thisSessionId.c_str()); ++ } ++ // Finally remove the session lock which was created on bootup of the session ++ sessionLock.unlink(); ++ } + } ++ + void Controller::statLeadOut(){} + + /// Returns true if this stream has at least one connected client. + bool Controller::hasViewers(std::string streamName){ + if (sessions.size()){ + long long currTime = Util::bootSecs(); +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- if (it->first.streamName == streamName && ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ ++ if (it->second.getStreamName() == streamName && + (it->second.hasDataFor(currTime) || it->second.hasDataFor(currTime - 1))){ + return true; + } +@@ -1377,7 +1049,6 @@ void Controller::fillClients(JSON::Value &req, JSON::Value &rep){ + if (fields & STAT_CLI_UP){rep["fields"].append("up");} + if (fields & STAT_CLI_BPS_DOWN){rep["fields"].append("downbps");} + if (fields & STAT_CLI_BPS_UP){rep["fields"].append("upbps");} +- if (fields & STAT_CLI_CRC){rep["fields"].append("crc");} + if (fields & STAT_CLI_SESSID){rep["fields"].append("sessid");} + if (fields & STAT_CLI_PKTCOUNT){rep["fields"].append("pktcount");} + if (fields & STAT_CLI_PKTLOST){rep["fields"].append("pktlost");} +@@ -1386,26 +1057,25 @@ void Controller::fillClients(JSON::Value &req, JSON::Value &rep){ + rep["data"].null(); + // loop over all sessions + if (sessions.size()){ +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ + unsigned long long time = reqTime; + if (now && reqTime - it->second.getEnd() < 5){time = it->second.getEnd();} + // data present and wanted? insert it! + if ((it->second.getEnd() >= time && it->second.getStart() <= time) && +- (!streams.size() || streams.count(it->first.streamName)) && +- (!protos.size() || protos.count(it->first.connector))){ ++ (!streams.size() || streams.count(it->second.getStreamName())) && ++ (!protos.size() || protos.count(it->second.getCurrentProtocols()))){ + if (it->second.hasDataFor(time)){ + JSON::Value d; +- if (fields & STAT_CLI_HOST){d.append(it->first.host);} +- if (fields & STAT_CLI_STREAM){d.append(it->first.streamName);} +- if (fields & STAT_CLI_PROTO){d.append(it->first.connector);} ++ if (fields & STAT_CLI_HOST){d.append(it->second.getHost());} ++ if (fields & STAT_CLI_STREAM){d.append(it->second.getStreamName());} ++ if (fields & STAT_CLI_PROTO){d.append(it->second.getCurrentProtocols());} + if (fields & STAT_CLI_CONNTIME){d.append(it->second.getConnTime(time));} + if (fields & STAT_CLI_POSITION){d.append(it->second.getLastSecond(time));} + if (fields & STAT_CLI_DOWN){d.append(it->second.getDown(time));} + if (fields & STAT_CLI_UP){d.append(it->second.getUp(time));} + if (fields & STAT_CLI_BPS_DOWN){d.append(it->second.getBpsDown(time));} + if (fields & STAT_CLI_BPS_UP){d.append(it->second.getBpsUp(time));} +- if (fields & STAT_CLI_CRC){d.append(it->first.crc);} +- if (fields & STAT_CLI_SESSID){d.append(it->first.ID);} ++ if (fields & STAT_CLI_SESSID){d.append(it->second.getSessId());} + if (fields & STAT_CLI_PKTCOUNT){d.append(it->second.getPktCount(time));} + if (fields & STAT_CLI_PKTLOST){d.append(it->second.getPktLost(time));} + if (fields & STAT_CLI_PKTRETRANSMIT){d.append(it->second.getPktRetransmit(time));} +@@ -1463,12 +1133,12 @@ void Controller::fillHasStats(JSON::Value &req, JSON::Value &rep){ + { + tthread::lock_guard<tthread::mutex> guard(statsMutex); + if (sessions.size()){ +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ + if (it->second.getSessType() == SESS_INPUT){ +- streams.insert(it->first.streamName); ++ streams.insert(it->second.getStreamName()); + }else{ +- streams.insert(it->first.streamName); +- if (it->second.getSessType() == SESS_VIEWER){clients[it->first.streamName]++;} ++ streams.insert(it->second.getStreamName()); ++ if (it->second.getSessType() == SESS_VIEWER){clients[it->second.getStreamName()]++;} + } + } + } +@@ -1742,12 +1412,12 @@ void Controller::fillTotals(JSON::Value &req, JSON::Value &rep){ + // loop over all sessions + /// \todo Make the interval configurable instead of 1 second + if (sessions.size()){ +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ ++ for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ + // data present and wanted? insert it! + if ((it->second.getEnd() >= (unsigned long long)reqStart || + it->second.getStart() <= (unsigned long long)reqEnd) && +- (!streams.size() || streams.count(it->first.streamName)) && +- (!protos.size() || protos.count(it->first.connector))){ ++ (!streams.size() || streams.count(it->second.getStreamName())) && ++ (!protos.size() || protos.count(it->second.getCurrentProtocols()))){ + for (unsigned long long i = reqStart; i <= reqEnd; ++i){ + if (it->second.hasDataFor(i)){ + totalsCount[i].add(it->second.getBpsDown(i), it->second.getBpsUp(i), it->second.getSessType(), it->second.getPktCount(), it->second.getPktLost(), it->second.getPktRetransmit()); +@@ -1831,6 +1501,25 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + H.SetHeader("Server", APPIDENT); + H.StartResponse("200", "OK", H, conn, true); + ++ // Counters of current active viewers, inputs and outputs of the Session stats cache ++ std::map<std::string, uint32_t> outputs; ++ uint32_t totViewers = 0; ++ uint32_t totInputs = 0; ++ uint32_t totOutputs = 0; ++ for (uint64_t idx = 0; idx < statComm.recordCount(); idx++){ ++ if (statComm.getStatus(idx) == COMM_STATUS_INVALID || statComm.getStatus(idx) & COMM_STATUS_DISCONNECT){continue;} ++ const std::string thisSessId = statComm.getSessId(idx); ++ // Count active viewers, inputs, outputs and protocols ++ if (thisSessId[0] == 'I'){ ++ totInputs++; ++ }else if (thisSessId[0] == 'O'){ ++ totOutputs++; ++ outputs[statComm.getConnector(idx)]++; ++ }else{ ++ totViewers++; ++ } ++ } ++ + // Collect core server stats + uint64_t mem_total = 0, mem_free = 0, mem_bufcache = 0; + uint64_t bw_up_total = 0, bw_down_total = 0; +@@ -1904,109 +1593,69 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + response << "# TYPE mist_shm_used gauge\n"; + response << "mist_shm_used " << (shm_total - shm_free) << "\n\n"; + +- if (Controller::triggerStats.size()){ +- response << "# HELP mist_trigger_count Total executions for the given trigger\n"; +- response << "# HELP mist_trigger_time Total execution time in millis for the given trigger\n"; +- response << "# HELP mist_trigger_fails Total failed executions for the given trigger\n"; +- for (std::map<std::string, Controller::triggerLog>::iterator it = Controller::triggerStats.begin(); +- it != Controller::triggerStats.end(); it++){ +- response << "mist_trigger_count{trigger=\"" << it->first << "\"}" << it->second.totalCount << "\n"; +- response << "mist_trigger_time{trigger=\"" << it->first << "\"}" << it->second.ms << "\n"; +- response << "mist_trigger_fails{trigger=\"" << it->first << "\"}" << it->second.failCount << "\n"; ++ response << "# HELP mist_viewseconds_total Number of seconds any media was received by a viewer.\n"; ++ response << "# TYPE mist_viewseconds_total counter\n"; ++ response << "mist_viewseconds_total " << servSeconds + viewSecondsTotal << "\n"; ++ ++ response << "\n# HELP mist_sessions_count Counts of unique sessions by type since server " ++ "start.\n"; ++ response << "# TYPE mist_sessions_count counter\n"; ++ response << "mist_sessions_count{sessType=\"viewers\"}" << servViewers << "\n"; ++ response << "mist_sessions_count{sessType=\"incoming\"}" << servInputs << "\n"; ++ response << "mist_sessions_count{sessType=\"outgoing\"}" << servOutputs << "\n\n"; ++ ++ response << "# HELP mist_bw_total Count of bytes handled since server start, by direction.\n"; ++ response << "# TYPE mist_bw_total counter\n"; ++ response << "stat_bw_total{direction=\"up\"}" << bw_up_total << "\n"; ++ response << "stat_bw_total{direction=\"down\"}" << bw_down_total << "\n\n"; ++ response << "mist_bw_total{direction=\"up\"}" << servUpBytes << "\n"; ++ response << "mist_bw_total{direction=\"down\"}" << servDownBytes << "\n\n"; ++ response << "mist_bw_other{direction=\"up\"}" << servUpOtherBytes << "\n"; ++ response << "mist_bw_other{direction=\"down\"}" << servDownOtherBytes << "\n\n"; ++ response << "mist_bw_limit " << bwLimit << "\n\n"; ++ ++ response << "# HELP mist_packets_total Total number of packets sent/received/lost over lossy protocols, server-wide.\n"; ++ response << "# TYPE mist_packets_total counter\n"; ++ response << "mist_packets_total{pkttype=\"sent\"}" << servPackSent << "\n"; ++ response << "mist_packets_total{pkttype=\"lost\"}" << servPackLoss << "\n"; ++ response << "mist_packets_total{pkttype=\"retrans\"}" << servPackRetrans << "\n"; ++ ++ if (outputs.size()){ ++ response << "# HELP mist_outputs Number of viewers active right now, server-wide, by output type.\n"; ++ response << "# TYPE mist_outputs gauge\n"; ++ for (std::map<std::string, uint32_t>::iterator it = outputs.begin(); it != outputs.end(); ++it){ ++ response << "mist_outputs{output=\"" << it->first << "\"}" << it->second << "\n"; + } + response << "\n"; + } + + {// Scope for shortest possible blocking of statsMutex + tthread::lock_guard<tthread::mutex> guard(statsMutex); +- // collect the data first +- std::map<std::string, uint32_t> outputs; +- unsigned long totViewers = 0, totInputs = 0, totOutputs = 0; +- unsigned int tOut = Util::bootSecs() - STATS_DELAY; +- unsigned int tIn = Util::bootSecs() - STATS_INPUT_DELAY; +- // check all sessions +- if (sessions.size()){ +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- switch (it->second.getSessType()){ +- case SESS_UNSET: break; +- case SESS_VIEWER: +- if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){ +- outputs[it->first.connector]++; +- totViewers++; +- } +- break; +- case SESS_INPUT: +- if (it->second.hasDataFor(tIn) && it->second.isViewerOn(tIn)){totInputs++;} +- break; +- case SESS_OUTPUT: +- if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){totOutputs++;} +- break; +- } +- } +- } + +- response << "# HELP mist_sessions_total Number of sessions active right now, server-wide, by " +- "type.\n"; ++ response << "# HELP mist_sessions_total Number of sessions active right now, server-wide, by type.\n"; + response << "# TYPE mist_sessions_total gauge\n"; + response << "mist_sessions_total{sessType=\"viewers\"}" << totViewers << "\n"; + response << "mist_sessions_total{sessType=\"incoming\"}" << totInputs << "\n"; + response << "mist_sessions_total{sessType=\"outgoing\"}" << totOutputs << "\n"; +- response << "mist_sessions_total{sessType=\"cached\"}" << sessions.size() << "\n\n"; +- +- response << "# HELP mist_viewseconds_total Number of seconds any media was received by a viewer.\n"; +- response << "# TYPE mist_viewseconds_total counter\n"; +- response << "mist_viewseconds_total " << servSeconds << "\n"; ++ response << "mist_sessions_total{sessType=\"cached\"}" << sessions.size() << "\n"; + +- response << "# HELP mist_outputs Number of viewers active right now, server-wide, by output type.\n"; +- response << "# TYPE mist_outputs gauge\n"; +- for (std::map<std::string, uint32_t>::iterator it = outputs.begin(); it != outputs.end(); ++it){ +- response << "mist_outputs{output=\"" << it->first << "\"}" << it->second << "\n"; +- } +- response << "\n"; +- +- response << "# HELP mist_sessions_count Counts of unique sessions by type since server " +- "start.\n"; +- response << "# TYPE mist_sessions_count counter\n"; +- response << "mist_sessions_count{sessType=\"viewers\"}" << servViewers << "\n"; +- response << "mist_sessions_count{sessType=\"incoming\"}" << servInputs << "\n"; +- response << "mist_sessions_count{sessType=\"outgoing\"}" << servOutputs << "\n\n"; +- +- response << "# HELP mist_bw_total Count of bytes handled since server start, by direction.\n"; +- response << "# TYPE mist_bw_total counter\n"; +- response << "stat_bw_total{direction=\"up\"}" << bw_up_total << "\n"; +- response << "stat_bw_total{direction=\"down\"}" << bw_down_total << "\n\n"; +- response << "mist_bw_total{direction=\"up\"}" << servUpBytes << "\n"; +- response << "mist_bw_total{direction=\"down\"}" << servDownBytes << "\n\n"; +- response << "mist_bw_other{direction=\"up\"}" << servUpOtherBytes << "\n"; +- response << "mist_bw_other{direction=\"down\"}" << servDownOtherBytes << "\n\n"; +- response << "mist_bw_limit " << bwLimit << "\n\n"; +- +- response << "# HELP mist_packets_total Total number of packets sent/received/lost over lossy protocols, server-wide.\n"; +- response << "# TYPE mist_packets_total counter\n"; +- response << "mist_packets_total{pkttype=\"sent\"}" << servPackSent << "\n"; +- response << "mist_packets_total{pkttype=\"lost\"}" << servPackLoss << "\n"; +- response << "mist_packets_total{pkttype=\"retrans\"}" << servPackRetrans << "\n"; +- +- response << "\n# HELP mist_viewers Number of sessions by type and stream active right now.\n"; +- response << "# TYPE mist_viewers gauge\n"; +- response << "# HELP mist_viewcount Count of unique viewer sessions since stream start, per " ++ response << "\n# HELP mist_viewcount Count of unique viewer sessions since stream start, per " + "stream.\n"; + response << "# TYPE mist_viewcount counter\n"; +- response << "# HELP mist_bw Count of bytes handled since stream start, by direction.\n"; +- response << "# TYPE mist_bw counter\n"; + response << "# HELP mist_viewseconds Number of seconds any media was received by a viewer.\n"; + response << "# TYPE mist_viewseconds counter\n"; ++ response << "# HELP mist_bw Count of bytes handled since stream start, by direction.\n"; ++ response << "# TYPE mist_bw counter\n"; + response << "# HELP mist_packets Total number of packets sent/received/lost over lossy protocols.\n"; + response << "# TYPE mist_packets counter\n"; +- response << "mist_viewseconds_total " << servSeconds << "\n"; + for (std::map<std::string, struct streamTotals>::iterator it = streamStats.begin(); +- it != streamStats.end(); ++it){ ++ it != streamStats.end(); ++it){ + response << "mist_sessions{stream=\"" << it->first << "\",sessType=\"viewers\"}" +- << it->second.currViews << "\n"; ++ << it->second.currViews << "\n"; + response << "mist_sessions{stream=\"" << it->first << "\",sessType=\"incoming\"}" +- << it->second.currIns << "\n"; ++ << it->second.currIns << "\n"; + response << "mist_sessions{stream=\"" << it->first << "\",sessType=\"outgoing\"}" +- << it->second.currOuts << "\n"; ++ << it->second.currOuts << "\n"; + response << "mist_viewcount{stream=\"" << it->first << "\"}" << it->second.viewers << "\n"; + response << "mist_viewseconds{stream=\"" << it->first << "\"} " << it->second.viewSeconds << "\n"; + response << "mist_bw{stream=\"" << it->first << "\",direction=\"up\"}" << it->second.upBytes << "\n"; +@@ -2015,6 +1664,19 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + response << "mist_packets{stream=\"" << it->first << "\",pkttype=\"lost\"}" << it->second.packLoss << "\n"; + response << "mist_packets{stream=\"" << it->first << "\",pkttype=\"retrans\"}" << it->second.packRetrans << "\n"; + } ++ ++ if (Controller::triggerStats.size()){ ++ response << "\n# HELP mist_trigger_count Total executions for the given trigger\n"; ++ response << "# HELP mist_trigger_time Total execution time in millis for the given trigger\n"; ++ response << "# HELP mist_trigger_fails Total failed executions for the given trigger\n"; ++ for (std::map<std::string, Controller::triggerLog>::iterator it = Controller::triggerStats.begin(); ++ it != Controller::triggerStats.end(); it++){ ++ response << "mist_trigger_count{trigger=\"" << it->first << "\"}" << it->second.totalCount << "\n"; ++ response << "mist_trigger_time{trigger=\"" << it->first << "\"}" << it->second.ms << "\n"; ++ response << "mist_trigger_fails{trigger=\"" << it->first << "\"}" << it->second.failCount << "\n"; ++ } ++ response << "\n"; ++ } + } + H.Chunkify(response.str(), conn); + } +@@ -2026,58 +1688,33 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + resp["shm_total"] = shm_total; + resp["shm_used"] = (shm_total - shm_free); + resp["logs"] = Controller::logCounter; +- if (Controller::triggerStats.size()){ +- for (std::map<std::string, Controller::triggerLog>::iterator it = Controller::triggerStats.begin(); +- it != Controller::triggerStats.end(); it++){ +- JSON::Value &tVal = resp["triggers"][it->first]; +- tVal["count"] = it->second.totalCount; +- tVal["ms"] = it->second.ms; +- tVal["fails"] = it->second.failCount; +- } +- } ++ resp["curr"].append(totViewers); ++ resp["curr"].append(totInputs); ++ resp["curr"].append(totOutputs); ++ resp["tot"].append(servViewers); ++ resp["tot"].append(servInputs); ++ resp["tot"].append(servOutputs); ++ resp["st"].append(bw_up_total); ++ resp["st"].append(bw_down_total); ++ resp["bw"].append(servUpBytes); ++ resp["bw"].append(servDownBytes); ++ resp["pkts"].append(servPackSent); ++ resp["pkts"].append(servPackLoss); ++ resp["pkts"].append(servPackRetrans); ++ resp["bwlimit"] = bwLimit; + {// Scope for shortest possible blocking of statsMutex + tthread::lock_guard<tthread::mutex> guard(statsMutex); +- // collect the data first +- std::map<std::string, uint32_t> outputs; +- uint64_t totViewers = 0, totInputs = 0, totOutputs = 0; +- uint64_t tOut = Util::bootSecs() - STATS_DELAY; +- uint64_t tIn = Util::bootSecs() - STATS_INPUT_DELAY; +- // check all sessions +- if (sessions.size()){ +- for (std::map<sessIndex, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ +- switch (it->second.getSessType()){ +- case SESS_UNSET: break; +- case SESS_VIEWER: +- if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){ +- outputs[it->first.connector]++; +- totViewers++; +- } +- break; +- case SESS_INPUT: +- if (it->second.hasDataFor(tIn) && it->second.isViewerOn(tIn)){totInputs++;} +- break; +- case SESS_OUTPUT: +- if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){totOutputs++;} +- break; +- } ++ resp["curr"].append((uint64_t)sessions.size()); ++ ++ if (Controller::triggerStats.size()){ ++ for (std::map<std::string, Controller::triggerLog>::iterator it = Controller::triggerStats.begin(); ++ it != Controller::triggerStats.end(); it++){ ++ JSON::Value &tVal = resp["triggers"][it->first]; ++ tVal["count"] = it->second.totalCount; ++ tVal["ms"] = it->second.ms; ++ tVal["fails"] = it->second.failCount; + } + } +- +- resp["curr"].append(totViewers); +- resp["curr"].append(totInputs); +- resp["curr"].append(totOutputs); +- resp["curr"].append((uint64_t)sessions.size()); +- resp["tot"].append(servViewers); +- resp["tot"].append(servInputs); +- resp["tot"].append(servOutputs); +- resp["st"].append(bw_up_total); +- resp["st"].append(bw_down_total); +- resp["bw"].append(servUpBytes); +- resp["bw"].append(servDownBytes); +- resp["pkts"].append(servPackSent); +- resp["pkts"].append(servPackLoss); +- resp["pkts"].append(servPackRetrans); +- resp["bwlimit"] = bwLimit; + if (Storage["config"].isMember("location") && Storage["config"]["location"].isMember("lat") && Storage["config"]["location"].isMember("lon")){ + resp["loc"]["lat"] = Storage["config"]["location"]["lat"].asDouble(); + resp["loc"]["lon"] = Storage["config"]["location"]["lon"].asDouble(); +diff --git a/src/controller/controller_statistics.h b/src/controller/controller_statistics.h +index 1cc4a82d..f798f811 100644 +--- a/src/controller/controller_statistics.h ++++ b/src/controller/controller_statistics.h +@@ -18,8 +18,7 @@ + namespace Controller{ + + extern bool killOnExit; +- extern unsigned int maxConnsPerIP; +- ++ + /// This function is ran whenever a stream becomes active. + void streamStarted(std::string stream); + /// This function is ran whenever a stream becomes inactive. +@@ -35,34 +34,14 @@ namespace Controller{ + uint64_t pktCount; + uint64_t pktLost; + uint64_t pktRetransmit; ++ std::string connectors; + }; + + enum sessType{SESS_UNSET = 0, SESS_INPUT, SESS_OUTPUT, SESS_VIEWER}; + +- /// This is a comparison and storage class that keeps sessions apart from each other. +- /// Whenever two of these objects are not equal, it will create a new session. +- class sessIndex{ +- public: +- sessIndex(); +- sessIndex(const Comms::Statistics &statComm, size_t id); +- std::string ID; +- std::string host; +- unsigned int crc; +- std::string streamName; +- std::string connector; +- +- bool operator==(const sessIndex &o) const; +- bool operator!=(const sessIndex &o) const; +- bool operator>(const sessIndex &o) const; +- bool operator<=(const sessIndex &o) const; +- bool operator<(const sessIndex &o) const; +- bool operator>=(const sessIndex &o) const; +- std::string toStr(); +- }; +- + class statStorage{ + public: +- void update(Comms::Statistics &statComm, size_t index); ++ void update(Comms::Sessions &statComm, size_t index); + bool hasDataFor(unsigned long long); + statLog &getDataFor(unsigned long long); + std::map<unsigned long long, statLog> log; +@@ -75,36 +54,33 @@ namespace Controller{ + uint64_t firstActive; + uint64_t firstSec; + uint64_t lastSec; +- uint64_t wipedUp; +- uint64_t wipedDown; +- uint64_t wipedPktCount; +- uint64_t wipedPktLost; +- uint64_t wipedPktRetransmit; +- std::deque<statStorage> oldConns; + sessType sessionType; + bool tracked; + uint8_t noBWCount; ///< Set to 2 when not to count for external bandwidth ++ std::string streamName; ++ std::string host; ++ std::string curConnector; ++ std::string sessId; ++ + public: + statSession(); +- uint32_t invalidate(); +- uint32_t kill(); +- char sync; +- std::map<uint64_t, statStorage> curConns; ++ ~statSession(); ++ statStorage curData; + std::set<std::string> tags; + sessType getSessType(); +- void wipeOld(uint64_t); +- void finish(uint64_t index); +- void switchOverTo(statSession &newSess, uint64_t index); +- void update(uint64_t index, Comms::Statistics &data); +- void dropSession(const sessIndex &index); ++ void update(uint64_t index, Comms::Sessions &data); + uint64_t getStart(); + uint64_t getEnd(); + bool isViewerOn(uint64_t time); +- bool isConnected(); + bool isTracked(); + bool hasDataFor(uint64_t time); +- bool hasData(); ++ std::string getStreamName(); ++ std::string getHost(); ++ std::string getSessId(); ++ std::string getCurrentProtocols(); ++ uint64_t newestDataPoint(); + uint64_t getConnTime(uint64_t time); ++ uint64_t getConnTime(); + uint64_t getLastSecond(uint64_t time); + uint64_t getDown(uint64_t time); + uint64_t getUp(); +@@ -122,8 +98,6 @@ namespace Controller{ + uint64_t getBpsUp(uint64_t start, uint64_t end); + }; + +- extern std::map<sessIndex, statSession> sessions; +- extern std::map<unsigned long, sessIndex> connToSession; + extern tthread::mutex statsMutex; + extern uint64_t statDropoff; + +@@ -155,6 +129,7 @@ namespace Controller{ + void sessions_shutdown(const std::string &streamname, const std::string &protocol = ""); + bool hasViewers(std::string streamName); + void writeSessionCache(); /*LTS*/ ++ void killConnections(std::string sessId); + + #define PROMETHEUS_TEXT 0 + #define PROMETHEUS_JSON 1 +diff --git a/src/controller/controller_storage.cpp b/src/controller/controller_storage.cpp +index 58e7b521..bdd52893 100644 +--- a/src/controller/controller_storage.cpp ++++ b/src/controller/controller_storage.cpp +@@ -91,19 +91,6 @@ namespace Controller{ + rlxAccs->setString("tags", tags, newEndPos); + rlxAccs->setEndPos(newEndPos + 1); + } +- if (Triggers::shouldTrigger("USER_END", strm)){ +- std::stringstream plgen; +- plgen << sessId << "\n" +- << strm << "\n" +- << conn << "\n" +- << host << "\n" +- << duration << "\n" +- << up << "\n" +- << down << "\n" +- << tags; +- std::string payload = plgen.str(); +- Triggers::doTrigger("USER_END", payload, strm); +- } + } + + void normalizeTrustedProxies(JSON::Value &tp){ +@@ -450,7 +437,8 @@ namespace Controller{ + systemBoot = globAccX.getInt("systemBoot"); + } + if(!globAccX.getFieldAccX("defaultStream") +- || !globAccX.getFieldAccX("systemBoot")){ ++ || !globAccX.getFieldAccX("systemBoot") ++ || !globAccX.getFieldAccX("sessionMode")){ + globAccX.setReload(); + globCfg.master = true; + globCfg.close(); +@@ -461,12 +449,16 @@ namespace Controller{ + if (!globAccX.isReady()){ + globAccX.addField("defaultStream", RAX_128STRING); + globAccX.addField("systemBoot", RAX_64UINT); ++ globAccX.addField("sessionMode", RAX_64UINT); ++ if (!Storage["config"]["sessionMode"]){ ++ Storage["config"]["sessionMode"] = SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID; ++ } + globAccX.setRCount(1); + globAccX.setEndPos(1); + globAccX.setReady(); + } + globAccX.setString("defaultStream", Storage["config"]["defaultStream"].asStringRef()); +- globAccX.setInt("systemBoot", systemBoot); ++ globAccX.setInt("sessionMode", Storage["config"]["sessionMode"].asInt()); + globCfg.master = false; // leave the page after closing + } + } +diff --git a/src/input/input.cpp b/src/input/input.cpp +index a86fe3cd..0524f55b 100644 +--- a/src/input/input.cpp ++++ b/src/input/input.cpp +@@ -794,7 +794,7 @@ namespace Mist{ + void Input::streamMainLoop(){ + uint64_t statTimer = 0; + uint64_t startTime = Util::bootSecs(); +- Comms::Statistics statComm; ++ Comms::Connections statComm; + getNext(); + if (thisPacket && !userSelect.count(thisIdx)){ + userSelect[thisIdx].reload(streamName, thisIdx, COMM_STATUS_ACTIVE | COMM_STATUS_SOURCE | COMM_STATUS_DONOTTRACK); +@@ -820,7 +820,7 @@ namespace Mist{ + + if (Util::bootSecs() - statTimer > 1){ + // Connect to stats for INPUT detection +- if (!statComm){statComm.reload();} ++ if (!statComm){statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID);} + if (statComm){ + if (!statComm){ + config->is_active = false; +@@ -829,7 +829,6 @@ namespace Mist{ + } + uint64_t now = Util::bootSecs(); + statComm.setNow(now); +- statComm.setCRC(getpid()); + statComm.setStream(streamName); + statComm.setConnector("INPUT:" + capa["name"].asStringRef()); + statComm.setTime(now - startTime); +@@ -842,7 +841,7 @@ namespace Mist{ + } + } + +- void Input::connStats(Comms::Statistics &statComm){ ++ void Input::connStats(Comms::Connections &statComm){ + statComm.setUp(0); + statComm.setDown(streamByteCount()); + statComm.setHost(getConnectedBinHost()); +@@ -853,7 +852,7 @@ namespace Mist{ + uint64_t statTimer = 0; + uint64_t startTime = Util::bootSecs(); + size_t idx; +- Comms::Statistics statComm; ++ Comms::Connections statComm; + + + DTSC::Meta liveMeta(config->getString("streamname"), false); +@@ -985,7 +984,7 @@ namespace Mist{ + + if (Util::bootSecs() - statTimer > 1){ + // Connect to stats for INPUT detection +- if (!statComm){statComm.reload();} ++ if (!statComm){statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID);} + if (statComm){ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -994,7 +993,6 @@ namespace Mist{ + } + uint64_t now = Util::bootSecs(); + statComm.setNow(now); +- statComm.setCRC(getpid()); + statComm.setStream(streamName); + statComm.setConnector("INPUT:" + capa["name"].asStringRef()); + statComm.setTime(now - startTime); +diff --git a/src/input/input.h b/src/input/input.h +index 8d7e8891..ce7686c1 100644 +--- a/src/input/input.h ++++ b/src/input/input.h +@@ -69,7 +69,7 @@ namespace Mist{ + virtual void userOnActive(size_t id); + virtual void userOnDisconnect(size_t id); + virtual void userLeadOut(); +- virtual void connStats(Comms::Statistics & statComm); ++ virtual void connStats(Comms::Connections & statComm); + virtual void parseHeader(); + bool bufferFrame(size_t track, uint32_t keyNum); + +diff --git a/src/input/input_rtsp.cpp b/src/input/input_rtsp.cpp +index fef613bb..ebb812e1 100644 +--- a/src/input/input_rtsp.cpp ++++ b/src/input/input_rtsp.cpp +@@ -196,7 +196,7 @@ namespace Mist{ + } + + void InputRTSP::streamMainLoop(){ +- Comms::Statistics statComm; ++ Comms::Connections statComm; + uint64_t startTime = Util::epoch(); + uint64_t lastPing = Util::bootSecs(); + uint64_t lastSecs = 0; +@@ -210,7 +210,7 @@ namespace Mist{ + if (lastSecs != currSecs){ + lastSecs = currSecs; + // Connect to stats for INPUT detection +- statComm.reload(); ++ statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID); + if (statComm){ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -219,7 +219,6 @@ namespace Mist{ + } + uint64_t now = Util::bootSecs(); + statComm.setNow(now); +- statComm.setCRC(getpid()); + statComm.setStream(streamName); + statComm.setConnector("INPUT:" + capa["name"].asStringRef()); + statComm.setUp(tcpCon.dataUp()); +diff --git a/src/input/input_sdp.cpp b/src/input/input_sdp.cpp +index 62c02aef..3169a836 100644 +--- a/src/input/input_sdp.cpp ++++ b/src/input/input_sdp.cpp +@@ -193,7 +193,7 @@ namespace Mist{ + + // Updates stats and quits if parsePacket returns false + void InputSDP::streamMainLoop(){ +- Comms::Statistics statComm; ++ Comms::Connections statComm; + uint64_t startTime = Util::epoch(); + uint64_t lastSecs = 0; + // Get RTP packets from UDP socket and stop if this fails +@@ -202,7 +202,7 @@ namespace Mist{ + if (lastSecs != currSecs){ + lastSecs = currSecs; + // Connect to stats for INPUT detection +- statComm.reload(); ++ statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID); + if (statComm){ + if (statComm.getStatus() == COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -211,7 +211,6 @@ namespace Mist{ + } + uint64_t now = Util::bootSecs(); + statComm.setNow(now); +- statComm.setCRC(getpid()); + statComm.setStream(streamName); + statComm.setConnector("INPUT:" + capa["name"].asStringRef()); + statComm.setDown(bytesRead); +diff --git a/src/input/input_ts.cpp b/src/input/input_ts.cpp +index cfe3f7cd..23311dc0 100644 +--- a/src/input/input_ts.cpp ++++ b/src/input/input_ts.cpp +@@ -527,7 +527,7 @@ namespace Mist{ + void inputTS::streamMainLoop(){ + meta.removeTrack(tmpIdx); + INFO_MSG("Removed temptrack %zu", tmpIdx); +- Comms::Statistics statComm; ++ Comms::Connections statComm; + uint64_t downCounter = 0; + uint64_t startTime = Util::bootSecs(); + uint64_t noDataSince = Util::bootSecs(); +@@ -621,7 +621,7 @@ namespace Mist{ + // Check for and spawn threads here. + if (Util::bootSecs() - threadCheckTimer > 1){ + // Connect to stats for INPUT detection +- statComm.reload(); ++ statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID); + if (statComm){ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -630,7 +630,6 @@ namespace Mist{ + } + uint64_t now = Util::bootSecs(); + statComm.setNow(now); +- statComm.setCRC(getpid()); + statComm.setStream(streamName); + statComm.setConnector("INPUT:" + capa["name"].asStringRef()); + statComm.setUp(0); +diff --git a/src/input/input_tssrt.cpp b/src/input/input_tssrt.cpp +index 4219ebbc..8fef6d7d 100644 +--- a/src/input/input_tssrt.cpp ++++ b/src/input/input_tssrt.cpp +@@ -282,7 +282,7 @@ namespace Mist{ + + void inputTSSRT::setSingular(bool newSingular){singularFlag = newSingular;} + +- void inputTSSRT::connStats(Comms::Statistics &statComm){ ++ void inputTSSRT::connStats(Comms::Connections &statComm){ + statComm.setUp(srtConn.dataUp()); + statComm.setDown(srtConn.dataDown()); + statComm.setHost(getConnectedBinHost()); +diff --git a/src/input/input_tssrt.h b/src/input/input_tssrt.h +index 4f337b48..143174cb 100644 +--- a/src/input/input_tssrt.h ++++ b/src/input/input_tssrt.h +@@ -40,7 +40,7 @@ namespace Mist{ + + Socket::SRTConnection srtConn; + bool singularFlag; +- virtual void connStats(Comms::Statistics &statComm); ++ virtual void connStats(Comms::Connections &statComm); + + Util::ResizeablePointer rawBuffer; + size_t rawIdx; +diff --git a/src/output/output.cpp b/src/output/output.cpp +index 1fa86eee..50d67549 100644 +--- a/src/output/output.cpp ++++ b/src/output/output.cpp +@@ -7,7 +7,7 @@ + #include <sys/wait.h> + #include <unistd.h> + +-#include "output.h" ++#include "output.h" + #include <mist/bitfields.h> + #include <mist/defines.h> + #include <mist/h264.h> +@@ -92,7 +92,7 @@ namespace Mist{ + firstTime = 0; + firstPacketTime = 0xFFFFFFFFFFFFFFFFull; + lastPacketTime = 0; +- crc = getpid(); ++ sid = ""; + parseData = false; + wantRequest = true; + sought = false; +@@ -100,7 +100,7 @@ namespace Mist{ + isBlocking = false; + needsLookAhead = 0; + extraKeepAway = 0; +- lastStats = 0; ++ lastStats = 0xFFFFFFFFFFFFFFFFull; + maxSkipAhead = 7500; + uaDelay = 10; + realTime = 1000; +@@ -111,6 +111,7 @@ namespace Mist{ + lastPushUpdate = 0; + previousFile = ""; + currentFile = ""; ++ sessionMode = 0xFFFFFFFFFFFFFFFFull; + + lastRecv = Util::bootSecs(); + if (myConn){ +@@ -211,95 +212,9 @@ namespace Mist{ + onFail("Not allowed to play (CONN_PLAY)"); + } + } +- doSync(true); + /*LTS-END*/ + } + +- /// If called with force set to true and a USER_NEW trigger enabled, forces a sync immediately. +- /// Otherwise, does nothing unless the sync byte is set to 2, in which case it forces a sync as well. +- /// May be called recursively because it calls stats() which calls this function. +- /// If this happens, the extra calls to the function return instantly. +- void Output::doSync(bool force){ +- if (!statComm){return;} +- if (recursingSync){return;} +- recursingSync = true; +- if (statComm.getSync() == 2 || force){ +- if (getStatsName() == capa["name"].asStringRef() && Triggers::shouldTrigger("USER_NEW", streamName)){ +- // sync byte 0 = no sync yet, wait for sync from controller... +- char initialSync = 0; +- // attempt to load sync status from session cache in shm +- { +- IPC::semaphore cacheLock(SEM_SESSCACHE, O_RDWR, ACCESSPERMS, 16); +- if (cacheLock){cacheLock.wait();} +- IPC::sharedPage shmSessions(SHM_SESSIONS, SHM_SESSIONS_SIZE, false, false); +- if (shmSessions.mapped){ +- char shmEmpty[SHM_SESSIONS_ITEM]; +- memset(shmEmpty, 0, SHM_SESSIONS_ITEM); +- std::string host; +- Socket::hostBytesToStr(statComm.getHost().data(), 16, host); +- uint32_t shmOffset = 0; +- const std::string &cName = capa["name"].asStringRef(); +- while (shmOffset + SHM_SESSIONS_ITEM < SHM_SESSIONS_SIZE){ +- // compare crc +- if (*(uint32_t*)(shmSessions.mapped + shmOffset) == crc){ +- // compare stream name +- if (strncmp(shmSessions.mapped + shmOffset + 4, streamName.c_str(), 100) == 0){ +- // compare connector +- if (strncmp(shmSessions.mapped + shmOffset + 104, cName.c_str(), 20) == 0){ +- // compare host +- if (strncmp(shmSessions.mapped + shmOffset + 124, host.c_str(), 40) == 0){ +- initialSync = shmSessions.mapped[shmOffset + 164]; +- HIGH_MSG("Instant-sync from session cache to %u", (unsigned int)initialSync); +- break; +- } +- } +- } +- } +- // stop if we reached the end +- if (memcmp(shmSessions.mapped + shmOffset, shmEmpty, SHM_SESSIONS_ITEM) == 0){ +- break; +- } +- shmOffset += SHM_SESSIONS_ITEM; +- } +- } +- if (cacheLock){cacheLock.post();} +- } +- unsigned int i = 0; +- statComm.setSync(initialSync); +- // wait max 10 seconds for sync +- while ((!statComm.getSync() || statComm.getSync() == 2) && i++ < 100){ +- Util::wait(100); +- stats(true); +- } +- HIGH_MSG("USER_NEW sync achieved: %u", statComm.getSync()); +- // 1 = check requested (connection is new) +- if (statComm.getSync() == 1){ +- std::string payload = streamName + "\n" + getConnectedHost() + "\n" + +- JSON::Value(crc).asString() + "\n" + capa["name"].asStringRef() + +- "\n" + reqUrl + "\n" + statComm.getSessId(); +- if (!Triggers::doTrigger("USER_NEW", payload, streamName)){ +- onFail("Not allowed to play (USER_NEW)"); +- statComm.setSync(100); // 100 = denied +- }else{ +- statComm.setSync(10); // 10 = accepted +- } +- } +- // 100 = denied +- if (statComm.getSync() == 100){onFail("Not allowed to play (USER_NEW cache)");} +- if (statComm.getSync() == 0){ +- onFail("Not allowed to play (USER_NEW init timeout)", true); +- } +- if (statComm.getSync() == 2){ +- onFail("Not allowed to play (USER_NEW re-init timeout)", true); +- } +- // anything else = accepted +- }else{ +- statComm.setSync(10); // auto-accept if no trigger +- } +- } +- recursingSync = false; +- } +- + std::string Output::getConnectedHost(){return myConn.getHost();} + + std::string Output::getConnectedBinHost(){ +@@ -433,10 +348,10 @@ namespace Mist{ + + //Connect to stats reporting, if not connected already + if (!statComm){ +- statComm.reload(); ++ statComm.reload(streamName, getConnectedHost(), sid, capa["name"].asStringRef(), reqUrl, sessionMode); + stats(true); + } +- ++ + //push inputs do not need to wait for stream to be ready for playback + if (isPushing()){return;} + +@@ -986,7 +901,7 @@ namespace Mist{ + INFO_MSG("Will split recording every %lld seconds", atoll(targetParams["split"].c_str())); + targetParams["nxt-split"] = JSON::Value((int64_t)(seekPos + endRec)).asString(); + } +- // Duration to record in seconds. Overrides recstop. ++ // Duration to record in seconds. Oversides recstop. + if (targetParams.count("duration")){ + long long endRec = atoll(targetParams["duration"].c_str()) * 1000; + targetParams["recstop"] = JSON::Value((int64_t)(seekPos + endRec)).asString(); +@@ -1301,6 +1216,7 @@ namespace Mist{ + /// request URL (if any) + /// ~~~~~~~~~~~~~~~ + int Output::run(){ ++ sessionMode = Util::getGlobalConfig("sessionMode").asInt(); + /*LTS-START*/ + // Connect to file target, if needed + if (isFileTarget()){ +@@ -1507,6 +1423,8 @@ namespace Mist{ + /*LTS-END*/ + + disconnect(); ++ stats(true); ++ userSelect.clear(); + myConn.close(); + return 0; + } +@@ -1822,7 +1740,7 @@ namespace Mist{ + // also cancel if it has been less than a second since the last update + // unless force is set to true + uint64_t now = Util::bootSecs(); +- if (now == lastStats && !force){return;} ++ if (now <= lastStats && !force){return;} + + if (isRecording()){ + if(lastPushUpdate == 0){ +@@ -1861,13 +1779,17 @@ namespace Mist{ + } + } + +- if (!statComm){statComm.reload();} +- if (!statComm){return;} ++ if (!statComm){statComm.reload(streamName, getConnectedHost(), sid, capa["name"].asStringRef(), reqUrl, sessionMode);} ++ if (!statComm){return;} ++ if (statComm.getExit()){ ++ onFail("Shutting down since this session is not allowed to view this stream"); ++ return; ++ } + + lastStats = now; + +- VERYHIGH_MSG("Writing stats: %s, %s, %u, %" PRIu64 ", %" PRIu64, getConnectedHost().c_str(), streamName.c_str(), +- crc & 0xFFFFFFFFu, myConn.dataUp(), myConn.dataDown()); ++ VERYHIGH_MSG("Writing stats: %s, %s, %s, %" PRIu64 ", %" PRIu64, getConnectedHost().c_str(), streamName.c_str(), ++ sid.c_str(), myConn.dataUp(), myConn.dataDown()); + /*LTS-START*/ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + onFail("Shutting down on controller request"); +@@ -1875,9 +1797,6 @@ namespace Mist{ + } + /*LTS-END*/ + statComm.setNow(now); +- statComm.setHost(getConnectedBinHost()); +- statComm.setCRC(crc); +- statComm.setStream(streamName); + statComm.setConnector(getStatsName()); + connStats(now, statComm); + statComm.setLastSecond(thisPacket ? thisPacket.getTime() : 0); +@@ -1887,7 +1806,7 @@ namespace Mist{ + // Tag the session with the user agent + if (newUA && ((now - myConn.connTime()) >= uaDelay || !myConn) && UA.size()){ + std::string APIcall = +- "{\"tag_sessid\":{\"" + statComm.getSessId() + "\":" + JSON::string_escape("UA:" + UA) + "}}"; ++ "{\"tag_sessid\":{\"" + statComm.sessionId + "\":" + JSON::string_escape("UA:" + UA) + "}}"; + Socket::UDPConnection uSock; + uSock.SetDestination(UDP_API_HOST, UDP_API_PORT); + uSock.SendNow(APIcall); +@@ -1895,8 +1814,6 @@ namespace Mist{ + } + /*LTS-END*/ + +- doSync(); +- + if (isPushing()){ + for (std::map<size_t, Comms::Users>::iterator it = userSelect.begin(); it != userSelect.end(); it++){ + if (it->second.getStatus() & COMM_STATUS_REQDISCONNECT){ +@@ -1912,7 +1829,7 @@ namespace Mist{ + } + } + +- void Output::connStats(uint64_t now, Comms::Statistics &statComm){ ++ void Output::connStats(uint64_t now, Comms::Connections &statComm){ + statComm.setUp(myConn.dataUp()); + statComm.setDown(myConn.dataDown()); + statComm.setTime(now - myConn.connTime()); +diff --git a/src/output/output.h b/src/output/output.h +index 84d17482..173b3840 100644 +--- a/src/output/output.h ++++ b/src/output/output.h +@@ -86,7 +86,6 @@ namespace Mist{ + std::string hostLookup(std::string ip); + bool onList(std::string ip, std::string list); + std::string getCountry(std::string ip); +- void doSync(bool force = false); + /*LTS-END*/ + std::map<size_t, uint32_t> currentPage; + void loadPageForKey(size_t trackId, size_t keyNum); +@@ -105,6 +104,7 @@ namespace Mist{ + bool firstData; + uint64_t lastPushUpdate; + bool newUA; ++ + protected: // these are to be messed with by child classes + virtual bool inlineRestartCapable() const{ + return false; +@@ -122,15 +122,16 @@ namespace Mist{ + virtual std::string getStatsName(); + virtual bool hasSessionIDs(){return false;} + +- virtual void connStats(uint64_t now, Comms::Statistics &statComm); ++ virtual void connStats(uint64_t now, Comms::Connections &statComm); + + std::set<size_t> getSupportedTracks(const std::string &type = "") const; + + inline virtual bool keepGoing(){return config->is_active && myConn;} + +- Comms::Statistics statComm; ++ Comms::Connections statComm; + bool isBlocking; ///< If true, indicates that myConn is blocking. +- uint32_t crc; ///< Checksum, if any, for usage in the stats. ++ std::string sid; ///< Random identifier used to split connections into sessions ++ uint64_t sessionMode; + uint64_t nextKeyTime(); + + // stream delaying variables +diff --git a/src/output/output_cmaf.cpp b/src/output/output_cmaf.cpp +index 4582a8b6..c2fbc5bc 100644 +--- a/src/output/output_cmaf.cpp ++++ b/src/output/output_cmaf.cpp +@@ -101,7 +101,7 @@ namespace Mist{ + } + } + +- void OutCMAF::connStats(uint64_t now, Comms::Statistics &statComm){ ++ void OutCMAF::connStats(uint64_t now, Comms::Connections &statComm){ + // For non-push usage, call usual function. + if (!isRecording()){ + Output::connStats(now, statComm); +diff --git a/src/output/output_cmaf.h b/src/output/output_cmaf.h +index efc36511..390549cc 100644 +--- a/src/output/output_cmaf.h ++++ b/src/output/output_cmaf.h +@@ -39,7 +39,7 @@ namespace Mist{ + bool isReadyForPlay(); + + protected: +- virtual void connStats(uint64_t now, Comms::Statistics &statComm); ++ virtual void connStats(uint64_t now, Comms::Connections &statComm); + void onTrackEnd(size_t idx); + bool hasSessionIDs(){return !config->getBool("mergesessions");} + +@@ -72,6 +72,7 @@ namespace Mist{ + void startPushOut(); + void pushNext(); + ++ uint32_t crc; + HTTP::URL pushUrl; + std::map<size_t, CMAFPushTrack> pushTracks; + void setupTrackObject(size_t idx); +diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp +index 252f069a..f55b974d 100644 +--- a/src/output/output_http.cpp ++++ b/src/output/output_http.cpp +@@ -55,7 +55,6 @@ namespace Mist{ + } + + void HTTPOutput::onFail(const std::string &msg, bool critical){ +- INFO_MSG("Failing '%s': %s", H.url.c_str(), msg.c_str()); + if (!webSock && !isRecording() && !responded){ + H.Clean(); // make sure no parts of old requests are left in any buffers + H.SetHeader("Server", APPIDENT); +@@ -238,18 +237,6 @@ namespace Mist{ + } + /*LTS-END*/ + if (H.hasHeader("User-Agent")){UA = H.GetHeader("User-Agent");} +- if (hasSessionIDs()){ +- if (H.GetVar("sessId").size()){ +- std::string ua = H.GetVar("sessId"); +- crc = checksum::crc32(0, ua.data(), ua.size()); +- }else{ +- std::string ua = JSON::Value(getpid()).asString(); +- crc = checksum::crc32(0, ua.data(), ua.size()); +- } +- }else{ +- std::string mixed_ua = UA + H.GetHeader("X-Playback-Session-Id"); +- crc = checksum::crc32(0, mixed_ua.data(), mixed_ua.size()); +- } + + if (H.GetVar("audio") != ""){targetParams["audio"] = H.GetVar("audio");} + if (H.GetVar("video") != ""){targetParams["video"] = H.GetVar("video");} +@@ -281,6 +268,21 @@ namespace Mist{ + realTime = 0; + } + } ++ // Get session ID cookie or generate a random one if it wasn't set ++ if (!sid.size()){ ++ std::map<std::string, std::string> storage; ++ const std::string koekjes = H.GetHeader("Cookie"); ++ HTTP::parseVars(koekjes, storage); ++ if (storage.count("sid")){ ++ // Get sid cookie, which is used to divide connections into sessions ++ sid = storage.at("sid"); ++ }else{ ++ // Else generate one ++ const std::string newSid = UA + JSON::Value(getpid()).asString(); ++ sid = JSON::Value(checksum::crc32(0, newSid.data(), newSid.size())).asString(); ++ H.SetHeader("sid", sid.c_str()); ++ } ++ } + // Handle upgrade to websocket if the output supports it + std::string upgradeHeader = H.GetHeader("Upgrade"); + Util::stringToLower(upgradeHeader); +diff --git a/src/output/output_tssrt.cpp b/src/output/output_tssrt.cpp +index db07dc91..dc04b247 100644 +--- a/src/output/output_tssrt.cpp ++++ b/src/output/output_tssrt.cpp +@@ -344,7 +344,7 @@ namespace Mist{ + } + } + +- void OutTSSRT::connStats(uint64_t now, Comms::Statistics &statComm){ ++ void OutTSSRT::connStats(uint64_t now, Comms::Connections &statComm){ + if (!srtConn){return;} + statComm.setUp(srtConn.dataUp()); + statComm.setDown(srtConn.dataDown()); +diff --git a/src/output/output_tssrt.h b/src/output/output_tssrt.h +index 1423af8d..71c9b72f 100644 +--- a/src/output/output_tssrt.h ++++ b/src/output/output_tssrt.h +@@ -15,7 +15,7 @@ namespace Mist{ + bool isReadyForPlay(){return true;} + virtual void requestHandler(); + protected: +- virtual void connStats(uint64_t now, Comms::Statistics &statComm); ++ virtual void connStats(uint64_t now, Comms::Connections &statComm); + virtual std::string getConnectedHost(){return srtConn.remotehost;} + virtual std::string getConnectedBinHost(){return srtConn.getBinHost();} + +diff --git a/src/output/output_webrtc.cpp b/src/output/output_webrtc.cpp +index b4289b64..058cd737 100644 +--- a/src/output/output_webrtc.cpp ++++ b/src/output/output_webrtc.cpp +@@ -1015,7 +1015,7 @@ namespace Mist{ + } + } + +- void OutWebRTC::connStats(uint64_t now, Comms::Statistics &statComm){ ++ void OutWebRTC::connStats(uint64_t now, Comms::Connections &statComm){ + statComm.setUp(myConn.dataUp()); + statComm.setDown(myConn.dataDown()); + statComm.setPacketCount(totalPkts); +diff --git a/src/output/output_webrtc.h b/src/output/output_webrtc.h +index 9c3db580..b2b528c5 100644 +--- a/src/output/output_webrtc.h ++++ b/src/output/output_webrtc.h +@@ -144,7 +144,7 @@ namespace Mist{ + void onDTSCConverterHasInitData(const size_t trackID, const std::string &initData); + void onRTPPacketizerHasRTPPacket(const char *data, size_t nbytes); + void onRTPPacketizerHasRTCPPacket(const char *data, uint32_t nbytes); +- virtual void connStats(uint64_t now, Comms::Statistics &statComm); ++ virtual void connStats(uint64_t now, Comms::Connections &statComm); + + private: + uint64_t lastRecv; +diff --git a/src/process/process_exec.cpp b/src/process/process_exec.cpp +index 7b775848..34ac53fd 100644 +--- a/src/process/process_exec.cpp ++++ b/src/process/process_exec.cpp +@@ -72,7 +72,7 @@ namespace Mist{ + } + bool needsLock(){return false;} + bool isSingular(){return false;} +- void connStats(Comms::Statistics &statComm){ ++ void connStats(Comms::Connections &statComm){ + for (std::map<size_t, Comms::Users>::iterator it = userSelect.begin(); it != userSelect.end(); it++){ + if (it->second){it->second.setStatus(COMM_STATUS_DONOTTRACK | it->second.getStatus());} + } +@@ -117,7 +117,7 @@ namespace Mist{ + realTime = 0; + OutEBML::sendHeader(); + }; +- void connStats(uint64_t now, Comms::Statistics &statComm){ ++ void connStats(uint64_t now, Comms::Connections &statComm){ + for (std::map<size_t, Comms::Users>::iterator it = userSelect.begin(); it != userSelect.end(); it++){ + if (it->second){it->second.setStatus(COMM_STATUS_DONOTTRACK | it->second.getStatus());} + } +diff --git a/src/session.cpp b/src/session.cpp +new file mode 100644 +index 00000000..3865e0ec +--- /dev/null ++++ b/src/session.cpp +@@ -0,0 +1,367 @@ ++#include <mist/defines.h> ++#include <mist/stream.h> ++#include <mist/util.h> ++#include <mist/config.h> ++#include <mist/auth.h> ++#include <mist/comms.h> ++#include <mist/triggers.h> ++#include <signal.h> ++#include <stdio.h> ++// Stats of connections which have closed are added to these global counters ++uint64_t globalNow = 0; ++uint64_t globalTime = 0; ++uint64_t globalDown = 0; ++uint64_t globalUp = 0; ++uint64_t globalPktcount = 0; ++uint64_t globalPktloss = 0; ++uint64_t globalPktretrans = 0; ++// Counts the duration a connector has been active ++std::map<std::string, uint64_t> connectorCount; ++std::map<std::string, uint64_t> connectorLastActive; ++// Set to True when a session gets invalidated, so that we know to run a new USER_NEW trigger ++bool forceTrigger = false; ++void handleSignal(int signum){ ++ if (signum == SIGUSR1){ ++ forceTrigger = true; ++ } ++} ++ ++void userOnActive(uint64_t &connections){ ++ ++connections; ++} ++ ++std::string getEnvWithDefault(const std::string variableName, const std::string defaultValue){ ++ const char* value = getenv(variableName.c_str()); ++ if (value){ ++ unsetenv(variableName.c_str()); ++ return value; ++ }else{ ++ return defaultValue; ++ } ++} ++ ++/// \brief Adds stats of closed connections to global counters ++void userOnDisconnect(Comms::Connections & connections, size_t idx){ ++ std::string thisConnector = connections.getConnector(idx); ++ if (thisConnector != ""){ ++ connectorCount[thisConnector] += connections.getTime(idx); ++ } ++ globalTime += connections.getTime(idx); ++ globalDown += connections.getDown(idx); ++ globalUp += connections.getUp(idx); ++ globalPktcount += connections.getPacketCount(idx); ++ globalPktloss += connections.getPacketLostCount(idx); ++ globalPktretrans += connections.getPacketRetransmitCount(idx); ++} ++ ++int main(int argc, char **argv){ ++ Comms::Connections connections; ++ Comms::Sessions sessions; ++ uint64_t lastSeen = Util::bootSecs(); ++ uint64_t currentConnections = 0; ++ Util::redirectLogsIfNeeded(); ++ signal(SIGUSR1, handleSignal); ++ // Init config and parse arguments ++ Util::Config config = Util::Config("MistSession"); ++ JSON::Value option; ++ ++ option.null(); ++ option["arg_num"] = 1; ++ option["arg"] = "string"; ++ option["help"] = "Session identifier of the entire session"; ++ option["default"] = ""; ++ config.addOption("sessionid", option); ++ ++ option.null(); ++ option["long"] = "sessionmode"; ++ option["short"] = "m"; ++ option["arg"] = "integer"; ++ option["default"] = 0; ++ config.addOption("sessionmode", option); ++ ++ option.null(); ++ option["long"] = "streamname"; ++ option["short"] = "n"; ++ option["arg"] = "string"; ++ option["default"] = ""; ++ config.addOption("streamname", option); ++ ++ option.null(); ++ option["long"] = "ip"; ++ option["short"] = "i"; ++ option["arg"] = "string"; ++ option["default"] = ""; ++ config.addOption("ip", option); ++ ++ option.null(); ++ option["long"] = "sid"; ++ option["short"] = "s"; ++ option["arg"] = "string"; ++ option["default"] = ""; ++ config.addOption("sid", option); ++ ++ option.null(); ++ option["long"] = "protocol"; ++ option["short"] = "p"; ++ option["arg"] = "string"; ++ option["default"] = ""; ++ config.addOption("protocol", option); ++ ++ option.null(); ++ option["long"] = "requrl"; ++ option["short"] = "r"; ++ option["arg"] = "string"; ++ option["default"] = ""; ++ config.addOption("requrl", option); ++ ++ config.activate(); ++ if (!(config.parseArgs(argc, argv))){ ++ FAIL_MSG("Cannot start a new session due to invalid arguments"); ++ return 1; ++ } ++ ++ const uint64_t bootTime = Util::getMicros(); ++ // Get session ID, session mode and other variables used as payload for the USER_NEW and USER_END triggers ++ const std::string thisStreamName = config.getString("streamname"); ++ const std::string thisHost = config.getString("ip"); ++ const std::string thisSid = config.getString("sid"); ++ const std::string thisProtocol = config.getString("protocol"); ++ const std::string thisReqUrl = config.getString("requrl"); ++ const std::string thisSessionId = config.getString("sessionid"); ++ const uint64_t sessionMode = config.getInteger("sessionmode"); ++ ++ if (thisSessionId == "" || thisProtocol == "" || thisStreamName == ""){ ++ FAIL_MSG("Given the following incomplete arguments: SessionId: '%s', protocol: '%s', stream name: '%s'. Aborting opening a new session", ++ thisSessionId.c_str(), thisProtocol.c_str(), thisStreamName.c_str()); ++ return 1; ++ } ++ ++ MEDIUM_MSG("Starting a new session for sessionId '%s'", thisSessionId.c_str()); ++ if (sessionMode < 1 || sessionMode > 15) { ++ FAIL_MSG("Invalid session mode of value %lu. Should be larger than 0 and smaller than 16", sessionMode); ++ return 1; ++ } ++ ++ // Try to lock to ensure we are the only process initialising this session ++ IPC::semaphore sessionLock; ++ char semName[NAME_BUFFER_SIZE]; ++ snprintf(semName, NAME_BUFFER_SIZE, SEM_SESSION, thisSessionId.c_str()); ++ sessionLock.open(semName, O_CREAT | O_RDWR, ACCESSPERMS, 1); ++ // If the lock fails, the previous Session process must've failed in spectacular fashion ++ // It's the Controller's task to clean everything up. When the lock fails, this cleanup hasn't happened yet ++ if (!sessionLock.tryWaitOneSecond()){ ++ FAIL_MSG("Session '%s' already locked", thisSessionId.c_str()); ++ return 1; ++ } ++ ++ // Check if a page already exists for this session ID. If so, quit ++ { ++ IPC::sharedPage dataPage; ++ char userPageName[NAME_BUFFER_SIZE]; ++ snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_SESSIONS, thisSessionId.c_str()); ++ dataPage.init(userPageName, 0, false, false); ++ if (dataPage){ ++ INFO_MSG("Session '%s' already has a running process", thisSessionId.c_str()); ++ sessionLock.post(); ++ return 0; ++ } ++ } ++ ++ // Claim a spot in shared memory for this session on the global statistics page ++ sessions.reload(); ++ if (!sessions){ ++ FAIL_MSG("Unable to register entry for session '%s' on the stats page", thisSessionId.c_str()); ++ sessionLock.post(); ++ return 1; ++ } ++ // Open the shared memory page containing statistics for each individual connection in this session ++ connections.reload(thisStreamName, thisHost, thisSid, thisProtocol, thisReqUrl, sessionMode, true, false); ++ // Initialise global session data ++ sessions.setHost(thisHost); ++ sessions.setSessId(thisSessionId); ++ sessions.setStream(thisStreamName); ++ sessionLock.post(); ++ ++ // Determine session type, since triggers only get run for viewer type sessions ++ uint64_t thisType = 0; ++ if (thisSessionId[0] == 'I'){ ++ INFO_MSG("Started new input session %s in %lu microseconds", thisSessionId.c_str(), Util::getMicros(bootTime)); ++ thisType = 1; ++ } ++ else if (thisSessionId[0] == 'O'){ ++ INFO_MSG("Started new output session %s in %lu microseconds", thisSessionId.c_str(), Util::getMicros(bootTime)); ++ thisType = 2; ++ } ++ else{ ++ INFO_MSG("Started new viewer session %s in %lu microseconds", thisSessionId.c_str(), Util::getMicros(bootTime)); ++ } ++ ++ // Do a USER_NEW trigger if it is defined for this stream ++ if (!thisType && Triggers::shouldTrigger("USER_NEW", thisStreamName)){ ++ std::string payload = thisStreamName + "\n" + thisHost + "\n" + ++ thisSid + "\n" + thisProtocol + ++ "\n" + thisReqUrl + "\n" + thisSessionId; ++ if (!Triggers::doTrigger("USER_NEW", payload, thisStreamName)){ ++ // Mark all connections of this session as finished, since this viewer is not allowed to view this stream ++ connections.setExit(); ++ connections.finishAll(); ++ } ++ } ++ ++ uint64_t lastSecond = 0; ++ uint64_t now = 0; ++ uint64_t time = 0; ++ uint64_t down = 0; ++ uint64_t up = 0; ++ uint64_t pktcount = 0; ++ uint64_t pktloss = 0; ++ uint64_t pktretrans = 0; ++ std::string connector = ""; ++ // Stay active until Mist exits or we no longer have an active connection ++ while (config.is_active && (currentConnections || Util::bootSecs() - lastSeen <= 10)){ ++ time = 0; ++ connector = ""; ++ down = 0; ++ up = 0; ++ pktcount = 0; ++ pktloss = 0; ++ pktretrans = 0; ++ currentConnections = 0; ++ ++ // Count active connections ++ COMM_LOOP(connections, userOnActive(currentConnections), userOnDisconnect(connections, id)); ++ // Loop through all connection entries to get a summary of statistics ++ for (uint64_t idx = 0; idx < connections.recordCount(); idx++){ ++ if (connections.getStatus(idx) == COMM_STATUS_INVALID || connections.getStatus(idx) & COMM_STATUS_DISCONNECT){continue;} ++ uint64_t thisLastSecond = connections.getLastSecond(idx); ++ std::string thisConnector = connections.getConnector(idx); ++ // Save info on the latest active connection separately ++ if (thisLastSecond > lastSecond){ ++ lastSecond = thisLastSecond; ++ now = connections.getNow(idx); ++ } ++ connectorLastActive[thisConnector] = thisLastSecond; ++ // Sum all other variables ++ time += connections.getTime(idx); ++ down += connections.getDown(idx); ++ up += connections.getUp(idx); ++ pktcount += connections.getPacketCount(idx); ++ pktloss += connections.getPacketLostCount(idx); ++ pktretrans += connections.getPacketRetransmitCount(idx); ++ } ++ ++ // Convert connector duration to string ++ std::stringstream connectorSummary; ++ bool addDelimiter = false; ++ connectorSummary << "{"; ++ for (std::map<std::string, uint64_t>::iterator it = connectorLastActive.begin(); ++ it != connectorLastActive.end(); ++it){ ++ if (lastSecond - it->second < 10000){ ++ connectorSummary << (addDelimiter ? "," : "") << it->first; ++ addDelimiter = true; ++ } ++ } ++ connectorSummary << "}"; ++ ++ // Write summary to global statistics ++ sessions.setTime(time + globalTime); ++ sessions.setDown(down + globalDown); ++ sessions.setUp(up + globalUp); ++ sessions.setPacketCount(pktcount + globalPktcount); ++ sessions.setPacketLostCount(pktloss + globalPktloss); ++ sessions.setPacketRetransmitCount(pktretrans + globalPktretrans); ++ sessions.setLastSecond(lastSecond); ++ sessions.setConnector(connectorSummary.str()); ++ sessions.setNow(now); ++ ++ // Retrigger USER_NEW if a re-sync was requested ++ if (!thisType && forceTrigger){ ++ forceTrigger = false; ++ if (Triggers::shouldTrigger("USER_NEW", thisStreamName)){ ++ INFO_MSG("Triggering USER_NEW for stream %s", thisStreamName.c_str()); ++ std::string payload = thisStreamName + "\n" + thisHost + "\n" + ++ thisSid + "\n" + thisProtocol + ++ "\n" + thisReqUrl + "\n" + thisSessionId; ++ if (!Triggers::doTrigger("USER_NEW", payload, thisStreamName)){ ++ INFO_MSG("USER_NEW rejected stream %s", thisStreamName.c_str()); ++ connections.setExit(); ++ connections.finishAll(); ++ }else{ ++ INFO_MSG("USER_NEW accepted stream %s", thisStreamName.c_str()); ++ } ++ } ++ } ++ ++ // Invalidate connections if the session is marked as invalid ++ if(connections.getExit()){ ++ connections.finishAll(); ++ break; ++ } ++ // Remember latest activity so we know when this session ends ++ if (currentConnections){ ++ lastSeen = Util::bootSecs(); ++ } ++ Util::sleep(1000); ++ } ++ ++ // Trigger USER_END ++ if (!thisType && Triggers::shouldTrigger("USER_END", thisStreamName)){ ++ lastSecond = 0; ++ time = 0; ++ down = 0; ++ up = 0; ++ ++ // Get a final summary of this session ++ for (uint64_t idx = 0; idx < connections.recordCount(); idx++){ ++ if (connections.getStatus(idx) == COMM_STATUS_INVALID || connections.getStatus(idx) & COMM_STATUS_DISCONNECT){continue;} ++ uint64_t thisLastSecond = connections.getLastSecond(idx); ++ // Set last second to the latest entry ++ if (thisLastSecond > lastSecond){ ++ lastSecond = thisLastSecond; ++ } ++ // Count protocol durations across the entire session ++ std::string thisConnector = connections.getConnector(idx); ++ if (thisConnector != ""){ ++ connectorCount[thisConnector] += connections.getTime(idx); ++ } ++ // Sum all other variables ++ time += connections.getTime(idx); ++ down += connections.getDown(idx); ++ up += connections.getUp(idx); ++ } ++ ++ // Convert connector duration to string ++ std::stringstream connectorSummary; ++ bool addDelimiter = false; ++ connectorSummary << "{"; ++ for (std::map<std::string, uint64_t>::iterator it = connectorCount.begin(); ++ it != connectorCount.end(); ++it){ ++ connectorSummary << (addDelimiter ? "," : "") << it->first << ":" << it->second; ++ addDelimiter = true; ++ } ++ connectorSummary << "}"; ++ ++ const uint64_t duration = lastSecond - (bootTime / 1000); ++ std::stringstream summary; ++ summary << thisSessionId << "\n" ++ << thisStreamName << "\n" ++ << connectorSummary.str() << "\n" ++ << thisHost << "\n" ++ << duration << "\n" ++ << up << "\n" ++ << down << "\n" ++ << sessions.getTags(); ++ Triggers::doTrigger("USER_END", summary.str(), thisStreamName); ++ } ++ ++ if (!thisType && connections.getExit()){ ++ WARN_MSG("Session %s has been invalidated since it is not allowed to view stream %s", thisSessionId.c_str(), thisStreamName.c_str()); ++ uint64_t sleepStart = Util::bootSecs(); ++ // Keep session invalidated for 10 minutes, or until the session stops ++ while (config.is_active && sleepStart - Util::bootSecs() < 600){ ++ Util::sleep(1000); ++ } ++ } ++ INFO_MSG("Shutting down session %s", thisSessionId.c_str()); ++ return 0; ++} +-- +2.25.1 + + +From 8ac486b815cac711c434422a1b0955486c28bb68 Mon Sep 17 00:00:00 2001 +From: Marco van Dijk <marco@stronk.rocks> +Date: Wed, 16 Mar 2022 13:46:14 +0100 +Subject: [PATCH 27/38] Completed new sessions system + +Co-authored-by: Thulinma <jaron@vietors.com> +--- + lib/comms.cpp | 206 ++++++++---- + lib/comms.h | 36 +- + lib/defines.h | 2 +- + lib/hls_support.cpp | 12 +- + lib/http_parser.cpp | 6 +- + lib/http_parser.h | 2 +- + lib/socket.cpp | 10 + + lib/socket.h | 1 + + lib/websocket.cpp | 22 +- + lib/websocket.h | 2 +- + src/controller/controller.cpp | 18 + + src/controller/controller_api.cpp | 11 +- + src/controller/controller_statistics.cpp | 375 +++++++++++++-------- + src/controller/controller_statistics.h | 31 +- + src/controller/controller_storage.cpp | 28 +- + src/controller/controller_storage.h | 1 + + src/input/input.cpp | 21 +- + src/input/input_rtsp.cpp | 3 +- + src/input/input_sdp.cpp | 3 +- + src/input/input_ts.cpp | 3 +- + src/input/input_tsrist.cpp | 2 +- + src/input/input_tsrist.h | 2 +- + src/output/output.cpp | 40 ++- + src/output/output.h | 3 +- + src/output/output_cmaf.cpp | 27 +- + src/output/output_hls.cpp | 28 +- + src/output/output_http.cpp | 51 ++- + src/output/output_http_internal.cpp | 179 +++++----- + src/output/output_http_internal.h | 8 +- + src/output/output_sdp.cpp | 12 + + src/output/output_sdp.h | 2 + + src/output/output_ts.cpp | 12 + + src/output/output_ts.h | 2 + + src/output/output_tsrist.cpp | 16 +- + src/output/output_tsrist.h | 4 +- + src/session.cpp | 410 +++++++++++++---------- + 36 files changed, 981 insertions(+), 610 deletions(-) + +diff --git a/lib/comms.cpp b/lib/comms.cpp +index 85f1e6d7..14faa980 100644 +--- a/lib/comms.cpp ++++ b/lib/comms.cpp +@@ -3,6 +3,7 @@ + #include "comms.h" + #include "defines.h" + #include "encode.h" ++#include "stream.h" + #include "procs.h" + #include "timing.h" + #include <fcntl.h> +@@ -10,6 +11,34 @@ + #include "config.h" + + namespace Comms{ ++ uint8_t sessionViewerMode = SESS_BUNDLE_DEFAULT_VIEWER; ++ uint8_t sessionInputMode = SESS_BUNDLE_DEFAULT_OTHER; ++ uint8_t sessionOutputMode = SESS_BUNDLE_DEFAULT_OTHER; ++ uint8_t sessionUnspecifiedMode = 0; ++ uint8_t sessionStreamInfoMode = SESS_DEFAULT_STREAM_INFO_MODE; ++ uint8_t tknMode = SESS_TKN_DEFAULT_MODE; ++ ++ /// \brief Refreshes the session configuration if the last update was more than 5 seconds ago ++ void sessionConfigCache(){ ++ static uint64_t lastUpdate = 0; ++ if (Util::bootSecs() > lastUpdate + 5){ ++ VERYHIGH_MSG("Updating session config"); ++ JSON::Value tmpVal = Util::getGlobalConfig("sessionViewerMode"); ++ if (!tmpVal.isNull()){ sessionViewerMode = tmpVal.asInt(); } ++ tmpVal = Util::getGlobalConfig("sessionInputMode"); ++ if (!tmpVal.isNull()){ sessionInputMode = tmpVal.asInt(); } ++ tmpVal = Util::getGlobalConfig("sessionOutputMode"); ++ if (!tmpVal.isNull()){ sessionOutputMode = tmpVal.asInt(); } ++ tmpVal = Util::getGlobalConfig("sessionUnspecifiedMode"); ++ if (!tmpVal.isNull()){ sessionUnspecifiedMode = tmpVal.asInt(); } ++ tmpVal = Util::getGlobalConfig("sessionStreamInfoMode"); ++ if (!tmpVal.isNull()){ sessionStreamInfoMode = tmpVal.asInt(); } ++ tmpVal = Util::getGlobalConfig("tknMode"); ++ if (!tmpVal.isNull()){ tknMode = tmpVal.asInt(); } ++ lastUpdate = Util::bootSecs(); ++ } ++ } ++ + Comms::Comms(){ + index = INVALID_RECORD_INDEX; + currentSize = 0; +@@ -17,7 +46,7 @@ namespace Comms{ + } + + Comms::~Comms(){ +- if (index != INVALID_RECORD_INDEX){ ++ if (index != INVALID_RECORD_INDEX && status){ + setStatus(COMM_STATUS_DISCONNECT | getStatus()); + } + if (master){ +@@ -123,6 +152,10 @@ namespace Comms{ + return; + } + dataAccX = Util::RelAccX(dataPage.mapped); ++ if (dataAccX.isExit()){ ++ dataPage.close(); ++ return; ++ } + fieldAccess(); + if (index == INVALID_RECORD_INDEX || reIssue){ + size_t reqCount = dataAccX.getRCount(); +@@ -170,19 +203,30 @@ namespace Comms{ + + void Sessions::addFields(){ + Connections::addFields(); ++ dataAccX.addField("tags", RAX_STRING, 512); + dataAccX.addField("sessid", RAX_STRING, 80); + } + + void Sessions::nullFields(){ + Connections::nullFields(); + setSessId(""); ++ setTags(""); + } + + void Sessions::fieldAccess(){ + Connections::fieldAccess(); ++ tags = dataAccX.getFieldAccX("tags"); + sessId = dataAccX.getFieldAccX("sessid"); + } + ++ std::string Sessions::getTags() const{return tags.string(index);} ++ std::string Sessions::getTags(size_t idx) const{return (master ? tags.string(idx) : 0);} ++ void Sessions::setTags(std::string _sid){tags.set(_sid, index);} ++ void Sessions::setTags(std::string _sid, size_t idx){ ++ if (!master){return;} ++ tags.set(_sid, idx); ++ } ++ + Users::Users() : Comms(){} + + Users::Users(const Users &rhs) : Comms(){ +@@ -251,31 +295,60 @@ namespace Comms{ + keyNum.set(_keyNum, idx); + } + ++ ++ ++ void Connections::reload(const std::string & sessId, bool _master, bool reIssue){ ++ // Open SEM_SESSION ++ if(!sem){ ++ char semName[NAME_BUFFER_SIZE]; ++ snprintf(semName, NAME_BUFFER_SIZE, SEM_SESSION, sessId.c_str()); ++ sem.open(semName, O_RDWR, ACCESSPERMS, 1); ++ if (!sem){return;} ++ } ++ char userPageName[NAME_BUFFER_SIZE]; ++ snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_SESSIONS, sessId.c_str()); ++ Comms::reload(userPageName, COMMS_SESSIONS_INITSIZE, _master, reIssue); ++ } ++ + /// \brief Claims a spot on the connections page for the input/output which calls this function + /// Starts the MistSession binary for each session, which handles the statistics + /// and the USER_NEW and USER_END triggers + /// \param streamName: Name of the stream the input is providing or an output is making available to viewers + /// \param ip: IP address of the viewer which wants to access streamName. For inputs this value can be set to any value +- /// \param sid: Session ID given by the player or randomly generated ++ /// \param tkn: Session token given by the player or randomly generated + /// \param protocol: Protocol currently in use for this connection +- /// \param sessionMode: Determines how a viewer session is defined: +- // If set to 0, all connections with the same viewer IP and stream name are bundled. +- // If set to 1, all connections with the same viewer IP and player ID are bundled. +- // If set to 2, all connections with the same player ID and stream name are bundled. +- // If set to 3, all connections with the same viewer IP, player ID and stream name are bundled. + /// \param _master: If True, we are reading from this page. If False, we are writing (to our entry) on this page + /// \param reIssue: If True, claim a new entry on this page +- void Connections::reload(std::string streamName, std::string ip, std::string sid, std::string protocol, std::string reqUrl, uint64_t sessionMode, bool _master, bool reIssue){ +- if (sessionMode == 0xFFFFFFFFFFFFFFFFull){ +- FAIL_MSG("The session mode was not initialised properly. Assuming default behaviour of bundling by viewer IP, stream name and player id"); +- sessionMode = SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID; +- } ++ void Connections::reload(const std::string & streamName, const std::string & ip, const std::string & tkn, const std::string & protocol, const std::string & reqUrl, bool _master, bool reIssue){ ++ initialTkn = tkn; ++ uint8_t sessMode = sessionViewerMode; + // Generate a unique session ID for each viewer, input or output +- sessionId = generateSession(streamName, ip, sid, protocol, sessionMode); + if (protocol.size() >= 6 && protocol.substr(0, 6) == "INPUT:"){ +- sessionId = "I" + sessionId; ++ sessMode = sessionInputMode; ++ sessionId = "I" + generateSession(streamName, ip, tkn, protocol, sessMode); + }else if (protocol.size() >= 7 && protocol.substr(0, 7) == "OUTPUT:"){ +- sessionId = "O" + sessionId; ++ sessMode = sessionOutputMode; ++ sessionId = "O" + generateSession(streamName, ip, tkn, protocol, sessMode); ++ }else{ ++ // If the session only contains the HTTP connector, check sessionStreamInfoMode ++ if (protocol.size() == 4 && protocol == "HTTP"){ ++ if (sessionStreamInfoMode == SESS_HTTP_AS_VIEWER){ ++ sessionId = generateSession(streamName, ip, tkn, protocol, sessMode); ++ }else if (sessionStreamInfoMode == SESS_HTTP_AS_OUTPUT){ ++ sessMode = sessionOutputMode; ++ sessionId = "O" + generateSession(streamName, ip, tkn, protocol, sessMode); ++ }else if (sessionStreamInfoMode == SESS_HTTP_DISABLED){ ++ return; ++ }else if (sessionStreamInfoMode == SESS_HTTP_AS_UNSPECIFIED){ ++ // Set sessMode to include all variables when determining the session ID ++ sessMode = sessionUnspecifiedMode; ++ sessionId = "U" + generateSession(streamName, ip, tkn, protocol, sessMode); ++ }else{ ++ sessionId = generateSession(streamName, ip, tkn, protocol, sessMode); ++ } ++ }else{ ++ sessionId = generateSession(streamName, ip, tkn, protocol, sessMode); ++ } + } + char userPageName[NAME_BUFFER_SIZE]; + snprintf(userPageName, NAME_BUFFER_SIZE, COMMS_SESSIONS, sessionId.c_str()); +@@ -283,36 +356,59 @@ namespace Comms{ + if (!_master){ + dataPage.init(userPageName, 0, false, false); + if (!dataPage){ ++ std::string host; ++ Socket::hostBytesToStr(ip.data(), 16, host); + pid_t thisPid; + std::deque<std::string> args; + args.push_back(Util::getMyPath() + "MistSession"); + args.push_back(sessionId); +- args.push_back("--sessionmode"); +- args.push_back(JSON::Value(sessionMode).asString()); +- args.push_back("--streamname"); +- args.push_back(streamName); +- args.push_back("--ip"); +- args.push_back(ip); +- args.push_back("--sid"); +- args.push_back(sid); +- args.push_back("--protocol"); +- args.push_back(protocol); +- args.push_back("--requrl"); +- args.push_back(reqUrl); ++ ++ // First bit defines whether to include stream name ++ if (sessMode & 0x08){ ++ args.push_back("--streamname"); ++ args.push_back(streamName); ++ }else{ ++ setenv("SESSION_STREAM", streamName.c_str(), 1); ++ } ++ // Second bit defines whether to include viewer ip ++ if (sessMode & 0x04){ ++ args.push_back("--ip"); ++ args.push_back(host); ++ }else{ ++ setenv("SESSION_IP", host.c_str(), 1); ++ } ++ // Third bit defines whether to include tkn ++ if (sessMode & 0x02){ ++ args.push_back("--tkn"); ++ args.push_back(tkn); ++ }else{ ++ setenv("SESSION_TKN", tkn.c_str(), 1); ++ } ++ // Fourth bit defines whether to include protocol ++ if (sessMode & 0x01){ ++ args.push_back("--protocol"); ++ args.push_back(protocol); ++ }else{ ++ setenv("SESSION_PROTOCOL", protocol.c_str(), 1); ++ } ++ setenv("SESSION_REQURL", reqUrl.c_str(), 1); + int err = fileno(stderr); + thisPid = Util::Procs::StartPiped(args, 0, 0, &err); + Util::Procs::forget(thisPid); +- HIGH_MSG("Spawned new session executeable (pid %u) for sessionId '%s', corresponding to host %s and stream %s", thisPid, sessionId.c_str(), ip.c_str(), streamName.c_str()); ++ unsetenv("SESSION_STREAM"); ++ unsetenv("SESSION_IP"); ++ unsetenv("SESSION_TKN"); ++ unsetenv("SESSION_PROTOCOL"); ++ unsetenv("SESSION_REQURL"); + } + } +- // Open SEM_SESSION +- if(!sem){ +- char semName[NAME_BUFFER_SIZE]; +- snprintf(semName, NAME_BUFFER_SIZE, SEM_SESSION, sessionId.c_str()); +- sem.open(semName, O_RDWR, ACCESSPERMS, 1); ++ reload(sessionId, _master, reIssue); ++ if (index != INVALID_RECORD_INDEX){ ++ setConnector(protocol); ++ setHost(ip); ++ setStream(streamName); ++ VERYHIGH_MSG("Reloading connection. Claimed record %lu", index); + } +- Comms::reload(userPageName, COMMS_SESSIONS_INITSIZE, _master, reIssue); +- VERYHIGH_MSG("Reloading connection. Claimed record %lu", index); + } + + /// \brief Marks the data page as closed, so that we longer write any new data to is +@@ -341,7 +437,6 @@ namespace Comms{ + dataAccX.addField("host", RAX_RAW, 16); + dataAccX.addField("stream", RAX_STRING, 100); + dataAccX.addField("connector", RAX_STRING, 20); +- dataAccX.addField("tags", RAX_STRING, 512); + dataAccX.addField("pktcount", RAX_64UINT); + dataAccX.addField("pktloss", RAX_64UINT); + dataAccX.addField("pktretrans", RAX_64UINT); +@@ -349,7 +444,6 @@ namespace Comms{ + + void Connections::nullFields(){ + Comms::nullFields(); +- setTags(""); + setConnector(""); + setStream(""); + setHost(""); +@@ -373,7 +467,6 @@ namespace Comms{ + host = dataAccX.getFieldAccX("host"); + stream = dataAccX.getFieldAccX("stream"); + connector = dataAccX.getFieldAccX("connector"); +- tags = dataAccX.getFieldAccX("tags"); + pktcount = dataAccX.getFieldAccX("pktcount"); + pktloss = dataAccX.getFieldAccX("pktloss"); + pktretrans = dataAccX.getFieldAccX("pktretrans"); +@@ -461,14 +554,6 @@ namespace Comms{ + return false; + } + +- std::string Connections::getTags() const{return tags.string(index);} +- std::string Connections::getTags(size_t idx) const{return (master ? tags.string(idx) : 0);} +- void Connections::setTags(std::string _sid){tags.set(_sid, index);} +- void Connections::setTags(std::string _sid, size_t idx){ +- if (!master){return;} +- tags.set(_sid, idx); +- } +- + uint64_t Connections::getPacketCount() const{return pktcount.uint(index);} + uint64_t Connections::getPacketCount(size_t idx) const{ + return (master ? pktcount.uint(idx) : 0); +@@ -501,31 +586,32 @@ namespace Comms{ + + /// \brief Generates a session ID which is unique per viewer + /// \return generated session ID as string +- std::string Connections::generateSession(std::string streamName, std::string ip, std::string sid, std::string connector, uint64_t sessionMode){ ++ std::string Connections::generateSession(const std::string & streamName, const std::string & ip, const std::string & tkn, const std::string & connector, uint64_t sessionMode){ + std::string concat; ++ std::string debugMsg = "Generating session id based on"; + // First bit defines whether to include stream name +- if (sessionMode > 7){ ++ if (sessionMode & 0x08){ + concat += streamName; +- sessionMode -= 8; ++ debugMsg += " stream name '" + streamName + "'"; + } + // Second bit defines whether to include viewer ip +- if (sessionMode > 3){ ++ if (sessionMode & 0x04){ + concat += ip; +- sessionMode -= 4; ++ std::string ipHex; ++ Socket::hostBytesToStr(ip.c_str(), ip.size(), ipHex); ++ debugMsg += " IP '" + ipHex + "'"; + } +- // Third bit defines whether to include player ip +- if (sessionMode > 1){ +- concat += sid; +- sessionMode -= 2; ++ // Third bit defines whether to include client-side session token ++ if (sessionMode & 0x02){ ++ concat += tkn; ++ debugMsg += " session token '" + tkn + "'"; + } + // Fourth bit defines whether to include protocol +- if (sessionMode == 1){ ++ if (sessionMode & 0x01){ + concat += connector; +- sessionMode = 0; +- } +- if (sessionMode > 0){ +- WARN_MSG("Could not resolve session mode of value %lu", sessionMode); ++ debugMsg += " protocol '" + connector + "'"; + } ++ VERYHIGH_MSG("%s", debugMsg.c_str()); + return Secure::sha256(concat.c_str(), concat.length()); + } + }// namespace Comms +diff --git a/lib/comms.h b/lib/comms.h +index 9a5c0ea9..ec36dcb0 100644 +--- a/lib/comms.h ++++ b/lib/comms.h +@@ -9,13 +9,21 @@ + #define COMM_STATUS_REQDISCONNECT 0x10 + #define COMM_STATUS_ACTIVE 0x1 + #define COMM_STATUS_INVALID 0x0 ++#define SESS_BUNDLE_DEFAULT_VIEWER 14 ++#define SESS_BUNDLE_DEFAULT_OTHER 15 ++#define SESS_DEFAULT_STREAM_INFO_MODE 1 ++#define SESS_HTTP_AS_VIEWER 1 ++#define SESS_HTTP_AS_OUTPUT 2 ++#define SESS_HTTP_DISABLED 3 ++#define SESS_HTTP_AS_UNSPECIFIED 4 ++#define SESS_TKN_DEFAULT_MODE 15 + + + #define COMM_LOOP(comm, onActive, onDisconnect) \ + {\ + for (size_t id = 0; id < comm.recordCount(); id++){\ + if (comm.getStatus(id) == COMM_STATUS_INVALID){continue;}\ +- if (!Util::Procs::isRunning(comm.getPid(id))){\ ++ if (!(comm.getStatus(id) & COMM_STATUS_DISCONNECT) && comm.getPid(id) && !Util::Procs::isRunning(comm.getPid(id))){\ + comm.setStatus(COMM_STATUS_DISCONNECT | comm.getStatus(id), id);\ + }\ + onActive;\ +@@ -27,6 +35,14 @@ + } + + namespace Comms{ ++ extern uint8_t sessionViewerMode; ++ extern uint8_t sessionInputMode; ++ extern uint8_t sessionOutputMode; ++ extern uint8_t sessionUnspecifiedMode; ++ extern uint8_t sessionStreamInfoMode; ++ extern uint8_t tknMode; ++ void sessionConfigCache(); ++ + class Comms{ + public: + Comms(); +@@ -66,11 +82,13 @@ namespace Comms{ + + class Connections : public Comms{ + public: +- void reload(std::string streamName, std::string ip, std::string sid, std::string protocol, std::string reqUrl, uint64_t sessionMode, bool _master = false, bool reIssue = false); ++ void reload(const std::string & streamName, const std::string & ip, const std::string & tkn, const std::string & protocol, const std::string & reqUrl, bool _master = false, bool reIssue = false); ++ void reload(const std::string & sessId, bool _master = false, bool reIssue = false); + void unload(); + operator bool() const{return dataPage.mapped && (master || index != INVALID_RECORD_INDEX);} +- std::string generateSession(std::string streamName, std::string ip, std::string sid, std::string connector, uint64_t sessionMode); ++ std::string generateSession(const std::string & streamName, const std::string & ip, const std::string & tkn, const std::string & connector, uint64_t sessionMode); + std::string sessionId; ++ std::string initialTkn; + + void setExit(); + bool getExit(); +@@ -79,6 +97,8 @@ namespace Comms{ + virtual void nullFields(); + virtual void fieldAccess(); + ++ const std::string & getTkn() const{return initialTkn;} ++ + uint64_t getNow() const; + uint64_t getNow(size_t idx) const; + void setNow(uint64_t _now); +@@ -120,11 +140,6 @@ namespace Comms{ + void setConnector(std::string _connector, size_t idx); + bool hasConnector(size_t idx, std::string protocol); + +- std::string getTags() const; +- std::string getTags(size_t idx) const; +- void setTags(std::string _sid); +- void setTags(std::string _sid, size_t idx); +- + uint64_t getPacketCount() const; + uint64_t getPacketCount(size_t idx) const; + void setPacketCount(uint64_t _count); +@@ -197,5 +212,10 @@ namespace Comms{ + virtual void addFields(); + virtual void nullFields(); + virtual void fieldAccess(); ++ ++ std::string getTags() const; ++ std::string getTags(size_t idx) const; ++ void setTags(std::string _sid); ++ void setTags(std::string _sid, size_t idx); + }; + }// namespace Comms +diff --git a/lib/defines.h b/lib/defines.h +index 203b75db..d08d1d04 100644 +--- a/lib/defines.h ++++ b/lib/defines.h +@@ -231,7 +231,7 @@ static inline void show_stackframe(){} + #define SEM_TRACKLIST "/MstTRKS%s" //%s stream name + #define SEM_SESSION "MstSess%s" + #define SEM_SESSCACHE "/MstSessCacheLock" +-#define SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID 14 ++#define SESS_TIMEOUT 600 // Session timeout in seconds + #define SHM_CAPA "MstCapa" + #define SHM_PROTO "MstProt" + #define SHM_PROXY "MstProx" +diff --git a/lib/hls_support.cpp b/lib/hls_support.cpp +index c311a7ac..130e691d 100644 +--- a/lib/hls_support.cpp ++++ b/lib/hls_support.cpp +@@ -274,7 +274,7 @@ namespace HLS{ + if (trackData.mediaFormat == ".ts"){return;} + + result << "#EXT-X-MAP:URI=\"" << trackData.urlPrefix << "init" << trackData.mediaFormat; +- if (trackData.sessionId.size()){result << "?sessId=" << trackData.sessionId;} ++ if (trackData.sessionId.size()){result << "?tkn=" << trackData.sessionId;} + result << "\"\r\n"; + } + +@@ -327,7 +327,7 @@ namespace HLS{ + result << "?msn=" << fragData.currentFrag; + result << "&mTrack=" << trackData.timingTrackId; + result << "&dur=" << fragData.duration; +- if (trackData.sessionId.size()){result << "&sessId=" << trackData.sessionId;} ++ if (trackData.sessionId.size()){result << "&tkn=" << trackData.sessionId;} + result << "\r\n"; + } + +@@ -341,7 +341,7 @@ namespace HLS{ + result << "?msn=" << fragData.currentFrag; + result << "&mTrack=" << trackData.timingTrackId; + result << "&dur=" << duration; +- if (trackData.sessionId.size()){result << "&sessId=" << trackData.sessionId;} ++ if (trackData.sessionId.size()){result << "&tkn=" << trackData.sessionId;} + result << "\""; + + // NOTE: INDEPENDENT tags, specified ONLY for VIDEO tracks, indicate the first partial fragment +@@ -448,7 +448,7 @@ namespace HLS{ + result << "?msn=" << fragData.currentFrag - 1; + result << "&mTrack=" << trackData.timingTrackId; + result << "&dur=" << partDurationMaxMs; +- if (trackData.sessionId.size()){result << "&sessId=" << trackData.sessionId;} ++ if (trackData.sessionId.size()){result << "&tkn=" << trackData.sessionId;} + result << "\"\r\n"; + } + +@@ -509,7 +509,7 @@ namespace HLS{ + result << ",NAME=\"" << name << "\",URI=\"" << trackId << "/index.m3u8"; + result << "?mTrack=" << masterData.mainTrack; + result << "&iMsn=" << iFrag; +- if (masterData.hasSessId){result << "&sessId=" << masterData.sessId;} ++ if (masterData.sessId.size()){result << "&tkn=" << masterData.sessId;} + if (masterData.noLLHLS){result << "&llhls=0";} + result << "\"\r\n"; + } +@@ -529,7 +529,7 @@ namespace HLS{ + result << "/index.m3u8"; + result << "?mTrack=" << masterData.mainTrack; + result << "&iMsn=" << iFrag; +- if (masterData.hasSessId){result << "&sessId=" << masterData.sessId;} ++ if (masterData.sessId.size()){result << "&tkn=" << masterData.sessId;} + if (masterData.noLLHLS){result << "&llhls=0";} + result << "\r\n"; + } +diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp +index c08e3d56..113fdb51 100644 +--- a/lib/http_parser.cpp ++++ b/lib/http_parser.cpp +@@ -742,13 +742,13 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){ + + /// HTTP variable parser to std::map<std::string, std::string> structure. + /// Reads variables from data, decodes and stores them to storage. +-void HTTP::parseVars(const std::string &data, std::map<std::string, std::string> &storage){ ++void HTTP::parseVars(const std::string &data, std::map<std::string, std::string> &storage, const std::string & separator){ + std::string varname; + std::string varval; + // position where a part starts (e.g. after &) + size_t pos = 0; + while (pos < data.length()){ +- size_t nextpos = data.find('&', pos); ++ size_t nextpos = data.find(separator, pos); + if (nextpos == std::string::npos){nextpos = data.length();} + size_t eq_pos = data.find('=', pos); + if (eq_pos < nextpos){ +@@ -769,7 +769,7 @@ void HTTP::parseVars(const std::string &data, std::map<std::string, std::string> + break; + } + // erase & +- pos = nextpos + 1; ++ pos = nextpos + separator.size(); + } + } + +diff --git a/lib/http_parser.h b/lib/http_parser.h +index 9c843f20..a5528df3 100644 +--- a/lib/http_parser.h ++++ b/lib/http_parser.h +@@ -14,7 +14,7 @@ namespace HTTP{ + + /// HTTP variable parser to std::map<std::string, std::string> structure. + /// Reads variables from data, decodes and stores them to storage. +- void parseVars(const std::string &data, std::map<std::string, std::string> &storage); ++ void parseVars(const std::string &data, std::map<std::string, std::string> &storage, const std::string & separator = "&"); + + /// Simple class for reading and writing HTTP 1.0 and 1.1. + class Parser : public Util::DataCallback{ +diff --git a/lib/socket.cpp b/lib/socket.cpp +index 6d63af00..47b2b6bd 100644 +--- a/lib/socket.cpp ++++ b/lib/socket.cpp +@@ -166,6 +166,8 @@ bool Socket::isBinAddress(const std::string &binAddr, std::string addr){ + /// Converts the given address with optional subnet to binary IPv6 form. + /// Returns 16 bytes of address, followed by 1 byte of subnet bits, zero or more times. + std::string Socket::getBinForms(std::string addr){ ++ // Check for empty address ++ if (!addr.size()){return std::string(17, (char)0);} + // Check if we need to do prefix matching + uint8_t prefixLen = 128; + if (addr.find('/') != std::string::npos){ +@@ -1796,6 +1798,14 @@ void Socket::UDPConnection::GetDestination(std::string &destIp, uint32_t &port){ + FAIL_MSG("Could not get destination for UDP socket"); + }// Socket::UDPConnection GetDestination + ++/// Gets the properties of the receiving end of this UDP socket. ++/// This will be the receiving end for all SendNow calls. ++std::string Socket::UDPConnection::getBinDestination(){ ++ std::string binList = getIPv6BinAddr(*(sockaddr_in6*)destAddr); ++ if (binList.size() < 16){ return std::string("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16); } ++ return binList.substr(0, 16); ++}// Socket::UDPConnection GetDestination ++ + /// Returns the port number of the receiving end of this socket. + /// Returns 0 on error. + uint32_t Socket::UDPConnection::getDestPort() const{ +diff --git a/lib/socket.h b/lib/socket.h +index a85fbf39..b369ac84 100644 +--- a/lib/socket.h ++++ b/lib/socket.h +@@ -215,6 +215,7 @@ namespace Socket{ + void setBlocking(bool blocking); + void SetDestination(std::string hostname, uint32_t port); + void GetDestination(std::string &hostname, uint32_t &port); ++ std::string getBinDestination(); + const void * getDestAddr(){return destAddr;} + size_t getDestAddrLen(){return destAddr_size;} + std::string getBoundAddress(); +diff --git a/lib/websocket.cpp b/lib/websocket.cpp +index 05703b55..c82b4cba 100644 +--- a/lib/websocket.cpp ++++ b/lib/websocket.cpp +@@ -73,31 +73,31 @@ namespace HTTP{ + } + + /// Takes an incoming HTTP::Parser request for a Websocket, and turns it into one. +- Websocket::Websocket(Socket::Connection &c, HTTP::Parser &h) : C(c){ ++ Websocket::Websocket(Socket::Connection &c, const HTTP::Parser &req, HTTP::Parser &resp) : C(c){ + frameType = 0; + maskOut = false; +- std::string connHeader = h.GetHeader("Connection"); ++ std::string connHeader = req.GetHeader("Connection"); + Util::stringToLower(connHeader); + if (connHeader.find("upgrade") == std::string::npos){ + FAIL_MSG("Could not negotiate websocket, connection header incorrect (%s).", connHeader.c_str()); + C.close(); + return; + } +- std::string upgradeHeader = h.GetHeader("Upgrade"); ++ std::string upgradeHeader = req.GetHeader("Upgrade"); + Util::stringToLower(upgradeHeader); + if (upgradeHeader != "websocket"){ + FAIL_MSG("Could not negotiate websocket, upgrade header incorrect (%s).", upgradeHeader.c_str()); + C.close(); + return; + } +- if (h.GetHeader("Sec-WebSocket-Version") != "13"){ ++ if (req.GetHeader("Sec-WebSocket-Version") != "13"){ + FAIL_MSG("Could not negotiate websocket, version incorrect (%s).", +- h.GetHeader("Sec-WebSocket-Version").c_str()); ++ req.GetHeader("Sec-WebSocket-Version").c_str()); + C.close(); + return; + } + #ifdef SSL +- std::string client_key = h.GetHeader("Sec-WebSocket-Key"); ++ std::string client_key = req.GetHeader("Sec-WebSocket-Key"); + if (!client_key.size()){ + FAIL_MSG("Could not negotiate websocket, missing key!"); + C.close(); +@@ -105,15 +105,13 @@ namespace HTTP{ + } + #endif + +- h.Clean(); +- h.setCORSHeaders(); +- h.SetHeader("Upgrade", "websocket"); +- h.SetHeader("Connection", "Upgrade"); ++ resp.SetHeader("Upgrade", "websocket"); ++ resp.SetHeader("Connection", "Upgrade"); + #ifdef SSL +- h.SetHeader("Sec-WebSocket-Accept", calculateKeyAccept(client_key)); ++ resp.SetHeader("Sec-WebSocket-Accept", calculateKeyAccept(client_key)); + #endif + // H.SetHeader("Sec-WebSocket-Protocol", "json"); +- h.SendResponse("101", "Websocket away!", C); ++ resp.SendResponse("101", "Websocket away!", C); + } + + /// Loops calling readFrame until the connection is closed, sleeping in between reads if needed. +diff --git a/lib/websocket.h b/lib/websocket.h +index 819f18c9..07861a19 100644 +--- a/lib/websocket.h ++++ b/lib/websocket.h +@@ -7,7 +7,7 @@ + namespace HTTP{ + class Websocket{ + public: +- Websocket(Socket::Connection &c, HTTP::Parser &h); ++ Websocket(Socket::Connection &c, const HTTP::Parser &req, HTTP::Parser &resp); + Websocket(Socket::Connection &c, const HTTP::URL & url, std::map<std::string, std::string> * headers = 0); + Websocket(Socket::Connection &c, bool client); + operator bool() const; +diff --git a/src/controller/controller.cpp b/src/controller/controller.cpp +index 9e17ca6b..972c7ed7 100644 +--- a/src/controller/controller.cpp ++++ b/src/controller/controller.cpp +@@ -309,6 +309,24 @@ int main_loop(int argc, char **argv){ + Controller::Storage["config"]["prometheus"] = Controller::conf.getString("prometheus"); + Controller::Storage["config"]["accesslog"] = Controller::conf.getString("accesslog"); + Controller::normalizeTrustedProxies(Controller::Storage["config"]["trustedproxy"]); ++ if (!Controller::Storage["config"]["sessionViewerMode"]){ ++ Controller::Storage["config"]["sessionViewerMode"] = SESS_BUNDLE_DEFAULT_VIEWER; ++ } ++ if (!Controller::Storage["config"]["sessionInputMode"]){ ++ Controller::Storage["config"]["sessionInputMode"] = SESS_BUNDLE_DEFAULT_OTHER; ++ } ++ if (!Controller::Storage["config"]["sessionOutputMode"]){ ++ Controller::Storage["config"]["sessionOutputMode"] = SESS_BUNDLE_DEFAULT_OTHER; ++ } ++ if (!Controller::Storage["config"]["sessionUnspecifiedMode"]){ ++ Controller::Storage["config"]["sessionUnspecifiedMode"] = 0; ++ } ++ if (!Controller::Storage["config"]["sessionStreamInfoMode"]){ ++ Controller::Storage["config"]["sessionStreamInfoMode"] = SESS_DEFAULT_STREAM_INFO_MODE; ++ } ++ if (!Controller::Storage["config"].isMember("tknMode")){ ++ Controller::Storage["config"]["tknMode"] = SESS_TKN_DEFAULT_MODE; ++ } + Controller::prometheus = Controller::Storage["config"]["prometheus"].asStringRef(); + Controller::accesslog = Controller::Storage["config"]["accesslog"].asStringRef(); + Controller::writeConfig(); +diff --git a/src/controller/controller_api.cpp b/src/controller/controller_api.cpp +index 02491065..4e935aba 100644 +--- a/src/controller/controller_api.cpp ++++ b/src/controller/controller_api.cpp +@@ -188,7 +188,9 @@ void Controller::handleWebSocket(HTTP::Parser &H, Socket::Connection &C){ + std::string logs = H.GetVar("logs"); + std::string accs = H.GetVar("accs"); + bool doStreams = H.GetVar("streams").size(); +- HTTP::Websocket W(C, H); ++ HTTP::Parser req = H; ++ H.Clean(); ++ HTTP::Websocket W(C, req, H); + if (!W){return;} + + IPC::sharedPage shmLogs(SHM_STATE_LOGS, 1024 * 1024); +@@ -594,7 +596,12 @@ void Controller::handleAPICommands(JSON::Value &Request, JSON::Value &Response){ + out["prometheus"] = in["prometheus"]; + Controller::prometheus = out["prometheus"].asStringRef(); + } +- if (in.isMember("sessionMode")){out["sessionMode"] = in["sessionMode"];} ++ if (in.isMember("sessionViewerMode")){out["sessionViewerMode"] = in["sessionViewerMode"];} ++ if (in.isMember("sessionInputMode")){out["sessionInputMode"] = in["sessionInputMode"];} ++ if (in.isMember("sessionOutputMode")){out["sessionOutputMode"] = in["sessionOutputMode"];} ++ if (in.isMember("sessionUnspecifiedMode")){out["sessionUnspecifiedMode"] = in["sessionUnspecifiedMode"];} ++ if (in.isMember("sessionStreamInfoMode")){out["sessionStreamInfoMode"] = in["sessionStreamInfoMode"];} ++ if (in.isMember("tknMode")){out["tknMode"] = in["tknMode"];} + if (in.isMember("defaultStream")){out["defaultStream"] = in["defaultStream"];} + if (in.isMember("location") && in["location"].isObject()){ + out["location"]["lat"] = in["location"]["lat"].asDouble(); +diff --git a/src/controller/controller_statistics.cpp b/src/controller/controller_statistics.cpp +index 6e51f4ee..ffb89897 100644 +--- a/src/controller/controller_statistics.cpp ++++ b/src/controller/controller_statistics.cpp +@@ -58,6 +58,11 @@ static uint64_t cpu_use = 0; + char noBWCountMatches[1717]; + uint64_t bwLimit = 128 * 1024 * 1024; // gigabit default limit + ++const char nullAddress[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++static Controller::statLog emptyLogEntry = {0, 0, 0, 0, 0, 0 ,0 ,0, "", nullAddress, ""}; ++bool notEmpty(const Controller::statLog & dta){ ++ return dta.time || dta.firstActive || dta.lastSecond || dta.down || dta.up || dta.streamName.size() || dta.connectors.size(); ++} + + // For server-wide totals. Local to this file only. + struct streamTotals{ +@@ -66,9 +71,11 @@ struct streamTotals{ + uint64_t inputs; + uint64_t outputs; + uint64_t viewers; ++ uint64_t unspecified; + uint64_t currIns; + uint64_t currOuts; + uint64_t currViews; ++ uint64_t currUnspecified; + uint8_t status; + uint64_t viewSeconds; + uint64_t packSent; +@@ -84,6 +91,7 @@ static uint64_t servDownBytes = 0; + static uint64_t servUpOtherBytes = 0; + static uint64_t servDownOtherBytes = 0; + static uint64_t servInputs = 0; ++static uint64_t servUnspecified = 0; + static uint64_t servOutputs = 0; + static uint64_t servViewers = 0; + static uint64_t servSeconds = 0; +@@ -95,17 +103,19 @@ static uint64_t viewSecondsTotal = 0; + // Mapping of streamName -> summary of stream-wide statistics + static std::map<std::string, struct streamTotals> streamStats; + +-// If sessId does not exist yet in streamStats, create and init an entry for it +-static void createEmptyStatsIfNeeded(const std::string & sessId){ +- if (streamStats.count(sessId)){return;} +- streamTotals & sT = streamStats[sessId]; ++// If streamName does not exist yet in streamStats, create and init an entry for it ++static void createEmptyStatsIfNeeded(const std::string & streamName){ ++ if (streamStats.count(streamName)){return;} ++ streamTotals & sT = streamStats[streamName]; + sT.upBytes = 0; + sT.downBytes = 0; + sT.inputs = 0; + sT.outputs = 0; + sT.viewers = 0; ++ sT.unspecified = 0; + sT.currIns = 0; + sT.currOuts = 0; ++ sT.currUnspecified = 0; + sT.currViews = 0; + sT.status = 0; + sT.viewSeconds = 0; +@@ -335,15 +345,23 @@ void Controller::SharedMemStats(void *config){ + it->second.currViews = 0; + it->second.currIns = 0; + it->second.currOuts = 0; ++ it->second.currUnspecified = 0; + } + } + // wipe old statistics and set session type counters + if (sessions.size()){ + std::list<std::string> mustWipe; +- uint64_t cutOffPoint = Util::bootSecs() - STAT_CUTOFF; ++ // Ensure cutOffPoint is either time of boot or 10 minutes ago, whichever is closer. ++ // Prevents wrapping around to high values close to system boot time. ++ uint64_t cutOffPoint = Util::bootSecs(); ++ if (cutOffPoint > STAT_CUTOFF){ ++ cutOffPoint -= STAT_CUTOFF; ++ }else{ ++ cutOffPoint = 0; ++ } + for (std::map<std::string, statSession>::iterator it = sessions.begin(); it != sessions.end(); it++){ + // This part handles ending sessions, keeping them in cache for now +- if (it->second.getEnd() < cutOffPoint && it->second.newestDataPoint() < cutOffPoint){ ++ if (it->second.getEnd() < cutOffPoint){ + viewSecondsTotal += it->second.getConnTime(); + mustWipe.push_back(it->first); + // Don't count this session as a viewer +@@ -353,19 +371,24 @@ void Controller::SharedMemStats(void *config){ + switch (it->second.getSessType()){ + case SESS_UNSET: break; + case SESS_VIEWER: +- if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){ +- streamStats[it->first].currViews++; ++ if (it->second.hasDataFor(tOut)){ ++ streamStats[it->second.getStreamName()].currViews++; + } + servSeconds += it->second.getConnTime(); + break; + case SESS_INPUT: +- if (it->second.hasDataFor(tIn) && it->second.isViewerOn(tIn)){ +- streamStats[it->first].currIns++; ++ if (it->second.hasDataFor(tIn)){ ++ streamStats[it->second.getStreamName()].currIns++; + } + break; + case SESS_OUTPUT: +- if (it->second.hasDataFor(tOut) && it->second.isViewerOn(tOut)){ +- streamStats[it->first].currOuts++; ++ if (it->second.hasDataFor(tOut)){ ++ streamStats[it->second.getStreamName()].currOuts++; ++ } ++ break; ++ case SESS_UNSPECIFIED: ++ if (it->second.hasDataFor(tOut)){ ++ streamStats[it->second.getStreamName()].currUnspecified++; + } + break; + } +@@ -406,6 +429,7 @@ void Controller::SharedMemStats(void *config){ + strmStats->setInt("viewers", it->second.currViews, strmPos); + strmStats->setInt("inputs", it->second.currIns, strmPos); + strmStats->setInt("outputs", it->second.currOuts, strmPos); ++ strmStats->setInt("unspecified", it->second.currUnspecified, strmPos); + ++strmPos; + } + } +@@ -489,47 +513,46 @@ void Controller::killConnections(std::string sessId){ + + /// Updates the given active connection with new stats data. + void Controller::statSession::update(uint64_t index, Comms::Sessions &statComm){ +- if (host == ""){ +- Socket::hostBytesToStr(statComm.getHost(index).data(), 16, host); +- } +- if (streamName == ""){ +- streamName = statComm.getStream(index); +- } +- if (curConnector == ""){ +- curConnector = statComm.getConnector(index); +- } + if (sessId == ""){ + sessId = statComm.getSessId(index); + } +- // Export tags to session +- if (tags.size()){ +- std::stringstream tagStream; +- for (std::set<std::string>::iterator it = tags.begin(); it != tags.end(); ++it){ +- tagStream << "[" << *it << "]"; ++ ++ if (sessionType == SESS_UNSET){ ++ if (sessId[0] == 'I'){ ++ sessionType = SESS_INPUT; ++ }else if (sessId[0] == 'O'){ ++ sessionType = SESS_OUTPUT; ++ }else if (sessId[0] == 'U'){ ++ sessionType = SESS_UNSPECIFIED; ++ }else{ ++ sessionType = SESS_VIEWER; + } +- statComm.setTags(tagStream.str(), index); + } + ++ uint64_t prevNow = curData.log.size() ? curData.log.rbegin()->first : 0; ++ // only parse last received data, if newer ++ if (prevNow > statComm.getNow(index)){return;}; + long long prevDown = getDown(); + long long prevUp = getUp(); + uint64_t prevPktSent = getPktCount(); + uint64_t prevPktLost = getPktLost(); + uint64_t prevPktRetrans = getPktRetransmit(); ++ uint64_t prevFirstActive = getFirstActive(); ++ + curData.update(statComm, index); +- // store timestamp of first received data, if older +- if (firstSec > statComm.getNow(index)){firstSec = statComm.getNow(index);} +- uint64_t secIncr = 0; +- // store timestamp of last received data, if newer +- if (statComm.getNow(index) > lastSec){ +- lastSec = statComm.getNow(index); +- if (!tracked){ +- tracked = true; +- firstActive = firstSec; +- }else{ +- secIncr = (statComm.getNow(index) - lastSec); ++ const std::string& streamName = getStreamName(); ++ // Export tags to session ++ if (tags.size()){ ++ std::stringstream tagStream; ++ for (std::set<std::string>::iterator it = tags.begin(); it != tags.end(); ++it){ ++ tagStream << "[" << *it << "]"; + } +- lastSec = statComm.getNow(index); ++ statComm.setTags(tagStream.str(), index); ++ } else { ++ statComm.setTags("", index); + } ++ ++ uint64_t secIncr = prevFirstActive ? (statComm.getNow(index) - prevNow) : 0; + long long currDown = getDown(); + long long currUp = getUp(); + uint64_t currPktSent = getPktCount(); +@@ -537,7 +560,7 @@ void Controller::statSession::update(uint64_t index, Comms::Sessions &statComm){ + uint64_t currPktRetrans = getPktRetransmit(); + if (currUp - prevUp < 0 || currDown - prevDown < 0){ + INFO_MSG("Negative data usage! %lldu/%lldd (u%lld->%lld) in %s over %s, #%" PRIu64, currUp - prevUp, +- currDown - prevDown, prevUp, currUp, streamName.c_str(), curConnector.c_str(), index); ++ currDown - prevDown, prevUp, currUp, streamName.c_str(), curData.log.rbegin()->second.connectors.c_str(), index); + }else{ + if (!noBWCount){ + size_t bwMatchOffset = 0; +@@ -567,40 +590,38 @@ void Controller::statSession::update(uint64_t index, Comms::Sessions &statComm){ + servPackRetrans += currPktRetrans - prevPktRetrans; + } + } +- if (sessionType == SESS_UNSET){ +- if (curConnector.size() >= 5 && curConnector.substr(0, 5) == "INPUT"){ +- ++servInputs; +- createEmptyStatsIfNeeded(streamName); +- streamStats[streamName].inputs++; +- streamStats[streamName].currIns++; +- sessionType = SESS_INPUT; +- }else if (curConnector.size() >= 6 && curConnector.substr(0, 6) == "OUTPUT"){ +- ++servOutputs; +- createEmptyStatsIfNeeded(streamName); +- streamStats[streamName].outputs++; +- streamStats[streamName].currOuts++; +- sessionType = SESS_OUTPUT; +- }else{ +- ++servViewers; +- createEmptyStatsIfNeeded(streamName); +- streamStats[streamName].viewers++; +- streamStats[streamName].currViews++; +- sessionType = SESS_VIEWER; ++ if (!prevFirstActive && streamName.size()){ ++ createEmptyStatsIfNeeded(streamName); ++ switch(sessionType){ ++ case SESS_INPUT: ++ ++servInputs; ++ streamStats[streamName].inputs++; ++ break; ++ case SESS_OUTPUT: ++ ++servOutputs; ++ streamStats[streamName].outputs++; ++ break; ++ case SESS_VIEWER: ++ ++servViewers; ++ streamStats[streamName].viewers++; ++ break; ++ case SESS_UNSPECIFIED: ++ ++servUnspecified; ++ streamStats[streamName].unspecified++; ++ break; ++ case SESS_UNSET: ++ break; + } + } + // Only count connections that are countable + if (noBWCount != 2){ +- if (!streamName.size() || streamName[0] == 0){ +- if (streamStats.count(streamName)){streamStats.erase(streamName);} +- }else{ +- createEmptyStatsIfNeeded(streamName); +- streamStats[streamName].upBytes += currUp - prevUp; +- streamStats[streamName].downBytes += currDown - prevDown; +- streamStats[streamName].packSent += currPktSent - prevPktSent; +- streamStats[streamName].packLoss += currPktLost - prevPktLost; +- streamStats[streamName].packRetrans += currPktRetrans - prevPktRetrans; +- if (sessionType == SESS_VIEWER){streamStats[streamName].viewSeconds += secIncr;} +- } ++ createEmptyStatsIfNeeded(streamName); ++ streamStats[streamName].upBytes += currUp - prevUp; ++ streamStats[streamName].downBytes += currDown - prevDown; ++ streamStats[streamName].packSent += currPktSent - prevPktSent; ++ streamStats[streamName].packLoss += currPktLost - prevPktLost; ++ streamStats[streamName].packRetrans += currPktRetrans - prevPktRetrans; ++ if (sessionType == SESS_VIEWER){streamStats[streamName].viewSeconds += secIncr;} + } + } + +@@ -608,21 +629,10 @@ Controller::sessType Controller::statSession::getSessType(){ + return sessionType; + } + +-Controller::statSession::~statSession(){ +- if (!tracked){return;} +- switch (sessionType){ +- case SESS_INPUT: +- if (streamStats.count(streamName) && streamStats[streamName].currIns){streamStats[streamName].currIns--;} +- break; +- case SESS_OUTPUT: +- if (streamStats.count(streamName) && streamStats[streamName].currOuts){streamStats[streamName].currOuts--;} +- break; +- case SESS_VIEWER: +- if (streamStats.count(streamName) && streamStats[streamName].currViews){streamStats[streamName].currViews--;} +- break; +- default: break; +- } +- uint64_t duration = lastSec - firstActive; ++/// Ends the currently active session by inserting a null datapoint one second after the last datapoint ++void Controller::statSession::finish(){ ++ if (!getFirstActive()){return;} ++ uint64_t duration = getEnd() - getFirstActive(); + if (duration < 1){duration = 1;} + std::stringstream tagStream; + if (tags.size()){ +@@ -630,6 +640,9 @@ Controller::statSession::~statSession(){ + tagStream << "[" << *it << "]"; + } + } ++ const std::string& streamName = getStreamName(); ++ const std::string& curConnector = getConnectors(); ++ const std::string& host = getStrHost(); + Controller::logAccess(sessId, streamName, curConnector, host, duration, getUp(), + getDown(), tagStream.str()); + if (Controller::accesslog.size()){ +@@ -668,74 +681,99 @@ Controller::statSession::~statSession(){ + } + } + } +- tracked = false; +- firstActive = 0; +- firstSec = 0xFFFFFFFFFFFFFFFFull; +- lastSec = 0; +- sessionType = SESS_UNSET; ++ tags.clear(); ++ // Insert null datapoint ++ curData.log[curData.log.rbegin()->first + 1] = emptyLogEntry; + } + + /// Constructs an empty session + Controller::statSession::statSession(){ +- firstActive = 0; +- tracked = false; +- firstSec = 0xFFFFFFFFFFFFFFFFull; +- lastSec = 0; + sessionType = SESS_UNSET; + noBWCount = 0; +- streamName = ""; +- host = ""; +- curConnector = ""; + sessId = ""; + } + + /// Returns the first measured timestamp in this session. + uint64_t Controller::statSession::getStart(){ +- return firstSec; ++ if (!curData.log.size()){return 0;} ++ return curData.log.begin()->first; + } + + /// Returns the last measured timestamp in this session. + uint64_t Controller::statSession::getEnd(){ +- return lastSec; ++ if (!curData.log.size()){return 0;} ++ return curData.log.rbegin()->first; + } + + /// Returns true if there is data for this session at timestamp t. + bool Controller::statSession::hasDataFor(uint64_t t){ +- if (lastSec < t){return false;} +- if (firstSec > t){return false;} + if (curData.hasDataFor(t)){return true;} + return false; + } + +-/// Returns true if this session should count as a viewer on the given timestamp. +-bool Controller::statSession::isViewerOn(uint64_t t){ +- return getUp(t) + getDown(t); ++const std::string& Controller::statSession::getSessId(){ ++ return sessId; ++} ++ ++uint64_t Controller::statSession::getFirstActive(){ ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.firstActive; ++ } ++ return 0; ++} ++ ++const std::string& Controller::statSession::getStreamName(uint64_t t){ ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).streamName; ++ } ++ return emptyLogEntry.streamName; + } + +-std::string Controller::statSession::getStreamName(){ +- return streamName; ++const std::string& Controller::statSession::getStreamName(){ ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.streamName; ++ } ++ return emptyLogEntry.streamName; + } + +-std::string Controller::statSession::getHost(){ ++std::string Controller::statSession::getStrHost(uint64_t t){ ++ std::string host; ++ Socket::hostBytesToStr(getHost(t).data(), 16, host); + return host; + } + +-std::string Controller::statSession::getSessId(){ +- return sessId; ++std::string Controller::statSession::getStrHost(){ ++ std::string host; ++ Socket::hostBytesToStr(getHost().data(), 16, host); ++ return host; ++} ++ ++const std::string& Controller::statSession::getHost(uint64_t t){ ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).host; ++ } ++ return emptyLogEntry.host; + } + +-std::string Controller::statSession::getCurrentProtocols(){ +- return curConnector; ++const std::string& Controller::statSession::getHost(){ ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.host; ++ } ++ return emptyLogEntry.host; + } + +-/// Returns true if this session should be considered connected +-uint64_t Controller::statSession::newestDataPoint(){ +- return lastSec; ++const std::string& Controller::statSession::getConnectors(uint64_t t){ ++ if (curData.hasDataFor(t)){ ++ return curData.getDataFor(t).connectors; ++ } ++ return emptyLogEntry.connectors; + } + +-/// Returns true if this session has started (tracked == true) but not yet ended (log entry written) +-bool Controller::statSession::isTracked(){ +- return tracked; ++const std::string& Controller::statSession::getConnectors(){ ++ if (curData.log.size()){ ++ return curData.log.rbegin()->second.connectors; ++ } ++ return emptyLogEntry.connectors; + } + + /// Returns the cumulative connected time for this session at timestamp t. +@@ -842,7 +880,7 @@ uint64_t Controller::statSession::getPktRetransmit(){ + /// Returns the cumulative downloaded bytes per second for this session at timestamp t. + uint64_t Controller::statSession::getBpsDown(uint64_t t){ + uint64_t aTime = t - 5; +- if (aTime < firstSec){aTime = firstSec;} ++ if (aTime < curData.log.begin()->first){aTime = curData.log.begin()->first;} + if (t <= aTime){return 0;} + uint64_t valA = getDown(aTime); + uint64_t valB = getDown(t); +@@ -852,7 +890,7 @@ uint64_t Controller::statSession::getBpsDown(uint64_t t){ + /// Returns the cumulative uploaded bytes per second for this session at timestamp t. + uint64_t Controller::statSession::getBpsUp(uint64_t t){ + uint64_t aTime = t - 5; +- if (aTime < firstSec){aTime = firstSec;} ++ if (aTime < curData.log.begin()->first){aTime = curData.log.begin()->first;} + if (t <= aTime){return 0;} + uint64_t valA = getUp(aTime); + uint64_t valB = getUp(t); +@@ -867,17 +905,8 @@ bool Controller::statStorage::hasDataFor(unsigned long long t){ + + /// Returns a reference to the most current data available at timestamp t. + Controller::statLog &Controller::statStorage::getDataFor(unsigned long long t){ +- static statLog empty; + if (!log.size()){ +- empty.time = 0; +- empty.lastSecond = 0; +- empty.down = 0; +- empty.up = 0; +- empty.pktCount = 0; +- empty.pktLost = 0; +- empty.pktRetransmit = 0; +- empty.connectors = ""; +- return empty; ++ return emptyLogEntry; + } + std::map<unsigned long long, statLog>::iterator it = log.upper_bound(t); + if (it != log.begin()){it--;} +@@ -889,6 +918,11 @@ Controller::statLog &Controller::statStorage::getDataFor(unsigned long long t){ + void Controller::statStorage::update(Comms::Sessions &statComm, size_t index){ + statLog tmp; + tmp.time = statComm.getTime(index); ++ if (!log.size() || !log.rbegin()->second.firstActive){ ++ tmp.firstActive = statComm.getNow(index); ++ } else{ ++ tmp.firstActive = log.rbegin()->second.firstActive; ++ } + tmp.lastSecond = statComm.getLastSecond(index); + tmp.down = statComm.getDown(index); + tmp.up = statComm.getUp(index); +@@ -896,9 +930,19 @@ void Controller::statStorage::update(Comms::Sessions &statComm, size_t index){ + tmp.pktLost = statComm.getPacketLostCount(index); + tmp.pktRetransmit = statComm.getPacketRetransmitCount(index); + tmp.connectors = statComm.getConnector(index); ++ tmp.streamName = statComm.getStream(index); ++ tmp.host = statComm.getHost(index); + log[statComm.getNow(index)] = tmp; + // wipe data older than STAT_CUTOFF seconds +- while (log.size() && log.begin()->first < Util::bootSecs() - STAT_CUTOFF){log.erase(log.begin());} ++ // Ensure cutOffPoint is either time of boot or 10 minutes ago, whichever is closer. ++ // Prevents wrapping around to high values close to system boot time. ++ uint64_t cutOffPoint = Util::bootSecs(); ++ if (cutOffPoint > STAT_CUTOFF){ ++ cutOffPoint -= STAT_CUTOFF; ++ }else{ ++ cutOffPoint = 0; ++ } ++ while (log.size() && log.begin()->first < cutOffPoint){log.erase(log.begin());} + } + + void Controller::statLeadIn(){ +@@ -915,6 +959,7 @@ void Controller::statOnActive(size_t id){ + void Controller::statOnDisconnect(size_t id){ + // Check to see if cleanup is required (when a Session binary fails) + const std::string thisSessionId = statComm.getSessId(id); ++ sessions[thisSessionId].finish(); + // Try to lock to see if the session crashed during boot + IPC::semaphore sessionLock; + char semName[NAME_BUFFER_SIZE]; +@@ -932,7 +977,7 @@ void Controller::statOnDisconnect(size_t id){ + if(dataPage){ + // Session likely crashed while it was running + dataPage.init(userPageName, 1, true); +- FAIL_MSG("Session '%s' got canceled unexpectedly. Hoovering up the left overs...", thisSessionId.c_str()); ++ FAIL_MSG("Session '%s' got cancelled unexpectedly. Cleaning up the leftovers...", thisSessionId.c_str()); + } + // Finally remove the session lock which was created on bootup of the session + sessionLock.unlink(); +@@ -999,13 +1044,23 @@ void Controller::fillClients(JSON::Value &req, JSON::Value &rep){ + if (req.isMember("time")){reqTime = req["time"].asInt();} + // to make sure no nasty timing business takes place, we store the case "now" as a bool. + bool now = (reqTime == 0); +- //if greater than current bootsecs, assume unix time and subtract epoch from it +- if (reqTime > (int64_t)epoch - STAT_CUTOFF){reqTime -= (epoch-bSecs);} ++ //if in the last 600 seconds of unix time (or higher), assume unix time and subtract epoch from it ++ if (reqTime > (int64_t)epoch - STAT_CUTOFF){reqTime -= Controller::systemBoot/1000;} + // add the current time, if negative or zero. + if (reqTime < 0){reqTime += bSecs;} +- if (reqTime == 0){reqTime = bSecs - STAT_CUTOFF;} ++ if (reqTime == 0){ ++ // Ensure cutOffPoint is either time of boot or 10 minutes ago, whichever is closer. ++ // Prevents wrapping around to high values close to system boot time. ++ uint64_t cutOffPoint = bSecs; ++ if (cutOffPoint > STAT_CUTOFF){ ++ cutOffPoint -= STAT_CUTOFF; ++ }else{ ++ cutOffPoint = 0; ++ } ++ reqTime = cutOffPoint; ++ } + // at this point, we have the absolute timestamp in bootsecs. +- rep["time"] = reqTime + (epoch-bSecs); // fill the absolute timestamp ++ rep["time"] = reqTime + (Controller::systemBoot/1000); // fill the absolute timestamp + + unsigned int fields = 0; + // next, figure out the fields wanted +@@ -1062,13 +1117,14 @@ void Controller::fillClients(JSON::Value &req, JSON::Value &rep){ + if (now && reqTime - it->second.getEnd() < 5){time = it->second.getEnd();} + // data present and wanted? insert it! + if ((it->second.getEnd() >= time && it->second.getStart() <= time) && +- (!streams.size() || streams.count(it->second.getStreamName())) && +- (!protos.size() || protos.count(it->second.getCurrentProtocols()))){ +- if (it->second.hasDataFor(time)){ ++ (!streams.size() || streams.count(it->second.getStreamName(time))) && ++ (!protos.size() || protos.count(it->second.getConnectors(time)))){ ++ const statLog & dta = it->second.curData.getDataFor(time); ++ if (notEmpty(dta)){ + JSON::Value d; +- if (fields & STAT_CLI_HOST){d.append(it->second.getHost());} +- if (fields & STAT_CLI_STREAM){d.append(it->second.getStreamName());} +- if (fields & STAT_CLI_PROTO){d.append(it->second.getCurrentProtocols());} ++ if (fields & STAT_CLI_HOST){d.append(it->second.getStrHost(time));} ++ if (fields & STAT_CLI_STREAM){d.append(it->second.getStreamName(time));} ++ if (fields & STAT_CLI_PROTO){d.append(it->second.getConnectors(time));} + if (fields & STAT_CLI_CONNTIME){d.append(it->second.getConnTime(time));} + if (fields & STAT_CLI_POSITION){d.append(it->second.getLastSecond(time));} + if (fields & STAT_CLI_DOWN){d.append(it->second.getDown(time));} +@@ -1252,6 +1308,8 @@ void Controller::fillActive(JSON::Value &req, JSON::Value &rep){ + F = it->second.currIns; + }else if (j->asStringRef() == "outputs"){ + F = it->second.currOuts; ++ }else if (j->asStringRef() == "unspecified"){ ++ F = it->second.currUnspecified; + }else if (j->asStringRef() == "views"){ + F = it->second.viewers; + }else if (j->asStringRef() == "viewseconds"){ +@@ -1323,6 +1381,7 @@ public: + clients = 0; + inputs = 0; + outputs = 0; ++ unspecified = 0; + downbps = 0; + upbps = 0; + pktCount = 0; +@@ -1334,6 +1393,7 @@ public: + case Controller::SESS_VIEWER: clients++; break; + case Controller::SESS_INPUT: inputs++; break; + case Controller::SESS_OUTPUT: outputs++; break; ++ case Controller::SESS_UNSPECIFIED: unspecified++; break; + default: break; + } + downbps += down; +@@ -1345,6 +1405,7 @@ public: + uint64_t clients; + uint64_t inputs; + uint64_t outputs; ++ uint64_t unspecified; + uint64_t downbps; + uint64_t upbps; + uint64_t pktCount; +@@ -1363,11 +1424,21 @@ void Controller::fillTotals(JSON::Value &req, JSON::Value &rep){ + if (req.isMember("start")){reqStart = req["start"].asInt();} + if (req.isMember("end")){reqEnd = req["end"].asInt();} + //if the reqStart or reqEnd is greater than current bootsecs, assume unix time and subtract epoch from it +- if (reqStart > (int64_t)epoch - STAT_CUTOFF){reqStart -= (epoch-bSecs);} +- if (reqEnd > (int64_t)epoch - STAT_CUTOFF){reqEnd -= (epoch-bSecs);} ++ if (reqStart > (int64_t)epoch - STAT_CUTOFF){reqStart -= Controller::systemBoot/1000;} ++ if (reqEnd > (int64_t)epoch - STAT_CUTOFF){reqEnd -= Controller::systemBoot/1000;} + // add the current time, if negative or zero. + if (reqStart < 0){reqStart += bSecs;} +- if (reqStart == 0){reqStart = bSecs - STAT_CUTOFF;} ++ if (reqStart == 0){ ++ // Ensure cutOffPoint is either time of boot or 10 minutes ago, whichever is closer. ++ // Prevents wrapping around to high values close to system boot time. ++ uint64_t cutOffPoint = bSecs; ++ if (cutOffPoint > STAT_CUTOFF){ ++ cutOffPoint -= STAT_CUTOFF; ++ }else{ ++ cutOffPoint = 0; ++ } ++ reqStart = cutOffPoint; ++ } + if (reqEnd <= 0){reqEnd += bSecs;} + // at this point, reqStart and reqEnd are the absolute timestamp in bootsecs. + if (reqEnd < reqStart){reqEnd = reqStart;} +@@ -1417,7 +1488,7 @@ void Controller::fillTotals(JSON::Value &req, JSON::Value &rep){ + if ((it->second.getEnd() >= (unsigned long long)reqStart || + it->second.getStart() <= (unsigned long long)reqEnd) && + (!streams.size() || streams.count(it->second.getStreamName())) && +- (!protos.size() || protos.count(it->second.getCurrentProtocols()))){ ++ (!protos.size() || protos.count(it->second.getConnectors()))){ + for (unsigned long long i = reqStart; i <= reqEnd; ++i){ + if (it->second.hasDataFor(i)){ + totalsCount[i].add(it->second.getBpsDown(i), it->second.getBpsUp(i), it->second.getSessType(), it->second.getPktCount(), it->second.getPktLost(), it->second.getPktRetransmit()); +@@ -1436,8 +1507,8 @@ void Controller::fillTotals(JSON::Value &req, JSON::Value &rep){ + return; + } + // yay! We have data! +- rep["start"] = totalsCount.begin()->first + (epoch-bSecs); +- rep["end"] = totalsCount.rbegin()->first + (epoch-bSecs); ++ rep["start"] = totalsCount.begin()->first + (Controller::systemBoot/1000); ++ rep["end"] = totalsCount.rbegin()->first + (Controller::systemBoot/1000); + rep["data"].null(); + rep["interval"].null(); + uint64_t prevT = 0; +@@ -1506,12 +1577,15 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + uint32_t totViewers = 0; + uint32_t totInputs = 0; + uint32_t totOutputs = 0; ++ uint32_t totUnspecified = 0; + for (uint64_t idx = 0; idx < statComm.recordCount(); idx++){ + if (statComm.getStatus(idx) == COMM_STATUS_INVALID || statComm.getStatus(idx) & COMM_STATUS_DISCONNECT){continue;} + const std::string thisSessId = statComm.getSessId(idx); + // Count active viewers, inputs, outputs and protocols + if (thisSessId[0] == 'I'){ + totInputs++; ++ }else if (thisSessId[0] == 'U'){ ++ totUnspecified++; + }else if (thisSessId[0] == 'O'){ + totOutputs++; + outputs[statComm.getConnector(idx)]++; +@@ -1602,6 +1676,7 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + response << "# TYPE mist_sessions_count counter\n"; + response << "mist_sessions_count{sessType=\"viewers\"}" << servViewers << "\n"; + response << "mist_sessions_count{sessType=\"incoming\"}" << servInputs << "\n"; ++ response << "mist_sessions_count{sessType=\"unspecified\"}" << servUnspecified << "\n"; + response << "mist_sessions_count{sessType=\"outgoing\"}" << servOutputs << "\n\n"; + + response << "# HELP mist_bw_total Count of bytes handled since server start, by direction.\n"; +@@ -1637,6 +1712,7 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + response << "mist_sessions_total{sessType=\"viewers\"}" << totViewers << "\n"; + response << "mist_sessions_total{sessType=\"incoming\"}" << totInputs << "\n"; + response << "mist_sessions_total{sessType=\"outgoing\"}" << totOutputs << "\n"; ++ response << "mist_sessions_total{sessType=\"unspecified\"}" << totUnspecified << "\n"; + response << "mist_sessions_total{sessType=\"cached\"}" << sessions.size() << "\n"; + + response << "\n# HELP mist_viewcount Count of unique viewer sessions since stream start, per " +@@ -1656,6 +1732,8 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + << it->second.currIns << "\n"; + response << "mist_sessions{stream=\"" << it->first << "\",sessType=\"outgoing\"}" + << it->second.currOuts << "\n"; ++ response << "mist_sessions{stream=\"" << it->first << "\",sessType=\"unspecified\"}" ++ << it->second.currUnspecified << "\n"; + response << "mist_viewcount{stream=\"" << it->first << "\"}" << it->second.viewers << "\n"; + response << "mist_viewseconds{stream=\"" << it->first << "\"} " << it->second.viewSeconds << "\n"; + response << "mist_bw{stream=\"" << it->first << "\",direction=\"up\"}" << it->second.upBytes << "\n"; +@@ -1691,9 +1769,11 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + resp["curr"].append(totViewers); + resp["curr"].append(totInputs); + resp["curr"].append(totOutputs); ++ resp["curr"].append(totUnspecified); + resp["tot"].append(servViewers); + resp["tot"].append(servInputs); + resp["tot"].append(servOutputs); ++ resp["tot"].append(servUnspecified); + resp["st"].append(bw_up_total); + resp["st"].append(bw_down_total); + resp["bw"].append(servUpBytes); +@@ -1735,6 +1815,7 @@ void Controller::handlePrometheus(HTTP::Parser &H, Socket::Connection &conn, int + resp["streams"][it->first]["curr"].append(it->second.currViews); + resp["streams"][it->first]["curr"].append(it->second.currIns); + resp["streams"][it->first]["curr"].append(it->second.currOuts); ++ resp["streams"][it->first]["curr"].append(it->second.currUnspecified); + resp["streams"][it->first]["pkts"].append(it->second.packSent); + resp["streams"][it->first]["pkts"].append(it->second.packLoss); + resp["streams"][it->first]["pkts"].append(it->second.packRetrans); +diff --git a/src/controller/controller_statistics.h b/src/controller/controller_statistics.h +index f798f811..69605942 100644 +--- a/src/controller/controller_statistics.h ++++ b/src/controller/controller_statistics.h +@@ -28,16 +28,19 @@ namespace Controller{ + + struct statLog{ + uint64_t time; ++ uint64_t firstActive; + uint64_t lastSecond; + uint64_t down; + uint64_t up; + uint64_t pktCount; + uint64_t pktLost; + uint64_t pktRetransmit; ++ std::string streamName; ++ std::string host; + std::string connectors; + }; + +- enum sessType{SESS_UNSET = 0, SESS_INPUT, SESS_OUTPUT, SESS_VIEWER}; ++ enum sessType{SESS_UNSET = 0, SESS_INPUT, SESS_OUTPUT, SESS_VIEWER, SESS_UNSPECIFIED}; + + class statStorage{ + public: +@@ -51,34 +54,30 @@ namespace Controller{ + /// Allows for moving of connections to another session. + class statSession{ + private: +- uint64_t firstActive; +- uint64_t firstSec; +- uint64_t lastSec; + sessType sessionType; +- bool tracked; + uint8_t noBWCount; ///< Set to 2 when not to count for external bandwidth +- std::string streamName; +- std::string host; +- std::string curConnector; + std::string sessId; + + public: + statSession(); +- ~statSession(); ++ void finish(); + statStorage curData; + std::set<std::string> tags; + sessType getSessType(); + void update(uint64_t index, Comms::Sessions &data); + uint64_t getStart(); + uint64_t getEnd(); +- bool isViewerOn(uint64_t time); +- bool isTracked(); + bool hasDataFor(uint64_t time); +- std::string getStreamName(); +- std::string getHost(); +- std::string getSessId(); +- std::string getCurrentProtocols(); +- uint64_t newestDataPoint(); ++ const std::string& getSessId(); ++ const std::string& getStreamName(uint64_t t); ++ const std::string& getStreamName(); ++ std::string getStrHost(uint64_t t); ++ std::string getStrHost(); ++ const std::string& getHost(uint64_t t); ++ const std::string& getHost(); ++ const std::string& getConnectors(uint64_t t); ++ const std::string& getConnectors(); ++ uint64_t getFirstActive(); + uint64_t getConnTime(uint64_t time); + uint64_t getConnTime(); + uint64_t getLastSecond(uint64_t time); +diff --git a/src/controller/controller_storage.cpp b/src/controller/controller_storage.cpp +index bdd52893..532ee4fe 100644 +--- a/src/controller/controller_storage.cpp ++++ b/src/controller/controller_storage.cpp +@@ -196,6 +196,7 @@ namespace Controller{ + rlxStrm->addField("viewers", RAX_64UINT); + rlxStrm->addField("inputs", RAX_64UINT); + rlxStrm->addField("outputs", RAX_64UINT); ++ rlxStrm->addField("unspecified", RAX_64UINT); + rlxStrm->setReady(); + } + rlxStrm->setRCount((1024 * 1024 - rlxStrm->getOffset()) / rlxStrm->getRSize()); +@@ -433,12 +434,17 @@ namespace Controller{ + + // if fields missing, recreate the page + if (globAccX.isReady()){ +- if(globAccX.getFieldAccX("systemBoot")){ ++ if(globAccX.getFieldAccX("systemBoot") && globAccX.getInt("systemBoot")){ + systemBoot = globAccX.getInt("systemBoot"); + } + if(!globAccX.getFieldAccX("defaultStream") + || !globAccX.getFieldAccX("systemBoot") +- || !globAccX.getFieldAccX("sessionMode")){ ++ || !globAccX.getFieldAccX("sessionViewerMode") ++ || !globAccX.getFieldAccX("sessionInputMode") ++ || !globAccX.getFieldAccX("sessionOutputMode") ++ || !globAccX.getFieldAccX("sessionUnspecifiedMode") ++ || !globAccX.getFieldAccX("sessionStreamInfoMode") ++ || !globAccX.getFieldAccX("tknMode")){ + globAccX.setReload(); + globCfg.master = true; + globCfg.close(); +@@ -449,16 +455,24 @@ namespace Controller{ + if (!globAccX.isReady()){ + globAccX.addField("defaultStream", RAX_128STRING); + globAccX.addField("systemBoot", RAX_64UINT); +- globAccX.addField("sessionMode", RAX_64UINT); +- if (!Storage["config"]["sessionMode"]){ +- Storage["config"]["sessionMode"] = SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID; +- } ++ globAccX.addField("sessionViewerMode", RAX_64UINT); ++ globAccX.addField("sessionInputMode", RAX_64UINT); ++ globAccX.addField("sessionOutputMode", RAX_64UINT); ++ globAccX.addField("sessionUnspecifiedMode", RAX_64UINT); ++ globAccX.addField("sessionStreamInfoMode", RAX_64UINT); ++ globAccX.addField("tknMode", RAX_64UINT); + globAccX.setRCount(1); + globAccX.setEndPos(1); + globAccX.setReady(); + } + globAccX.setString("defaultStream", Storage["config"]["defaultStream"].asStringRef()); +- globAccX.setInt("sessionMode", Storage["config"]["sessionMode"].asInt()); ++ globAccX.setInt("sessionViewerMode", Storage["config"]["sessionViewerMode"].asInt()); ++ globAccX.setInt("sessionInputMode", Storage["config"]["sessionInputMode"].asInt()); ++ globAccX.setInt("sessionOutputMode", Storage["config"]["sessionOutputMode"].asInt()); ++ globAccX.setInt("sessionUnspecifiedMode", Storage["config"]["sessionUnspecifiedMode"].asInt()); ++ globAccX.setInt("sessionStreamInfoMode", Storage["config"]["sessionStreamInfoMode"].asInt()); ++ globAccX.setInt("tknMode", Storage["config"]["tknMode"].asInt()); ++ globAccX.setInt("systemBoot", systemBoot); + globCfg.master = false; // leave the page after closing + } + } +diff --git a/src/controller/controller_storage.h b/src/controller/controller_storage.h +index 6339cfd0..974d989b 100644 +--- a/src/controller/controller_storage.h ++++ b/src/controller/controller_storage.h +@@ -16,6 +16,7 @@ namespace Controller{ + extern bool isTerminal; ///< True if connected to a terminal and not a log file. + extern bool isColorized; ///< True if we colorize the output + extern uint64_t logCounter; ///< Count of logged messages since boot ++ extern uint64_t systemBoot; ///< Unix time in milliseconds of system boot + + Util::RelAccX *logAccessor(); + Util::RelAccX *accesslogAccessor(); +diff --git a/src/input/input.cpp b/src/input/input.cpp +index 0524f55b..782dc4ef 100644 +--- a/src/input/input.cpp ++++ b/src/input/input.cpp +@@ -502,6 +502,7 @@ namespace Mist{ + } + + int Input::run(){ ++ Comms::sessionConfigCache(); + if (streamStatus){streamStatus.mapped[0] = STRMSTAT_BOOT;} + checkHeaderTimes(config->getString("input")); + if (needHeader()){ +@@ -623,6 +624,8 @@ namespace Mist{ + /// ~~~~~~~~~~~~~~~ + void Input::serve(){ + users.reload(streamName, true); ++ Comms::Connections statComm; ++ uint64_t startTime = Util::bootSecs(); + + if (!M){ + // Initialize meta page +@@ -636,6 +639,7 @@ namespace Mist{ + meta.setSource(config->getString("input")); + + bool internalOnly = (config->getString("input").find("INTERNAL_ONLY") != std::string::npos); ++ bool isBuffer = (capa["name"].asStringRef() == "Buffer"); + + /*LTS-START*/ + if (Triggers::shouldTrigger("STREAM_READY", config->getString("streamname"))){ +@@ -666,6 +670,18 @@ namespace Mist{ + }else{ + if (connectedUsers && M.getValidTracks().size()){activityCounter = Util::bootSecs();} + } ++ // Connect to stats for INPUT detection ++ if (!internalOnly && !isBuffer){ ++ if (!statComm){statComm.reload(streamName, getConnectedBinHost(), JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "");} ++ if (statComm){ ++ uint64_t now = Util::bootSecs(); ++ statComm.setNow(now); ++ statComm.setStream(streamName); ++ statComm.setTime(now - startTime); ++ statComm.setLastSecond(0); ++ connStats(statComm); ++ } ++ } + // if not shutting down, wait 1 second before looping + if (config->is_active){Util::wait(INPUT_USER_INTERVAL);} + } +@@ -820,7 +836,7 @@ namespace Mist{ + + if (Util::bootSecs() - statTimer > 1){ + // Connect to stats for INPUT detection +- if (!statComm){statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID);} ++ if (!statComm){statComm.reload(streamName, getConnectedBinHost(), JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "");} + if (statComm){ + if (!statComm){ + config->is_active = false; +@@ -830,7 +846,6 @@ namespace Mist{ + uint64_t now = Util::bootSecs(); + statComm.setNow(now); + statComm.setStream(streamName); +- statComm.setConnector("INPUT:" + capa["name"].asStringRef()); + statComm.setTime(now - startTime); + statComm.setLastSecond(0); + connStats(statComm); +@@ -984,7 +999,7 @@ namespace Mist{ + + if (Util::bootSecs() - statTimer > 1){ + // Connect to stats for INPUT detection +- if (!statComm){statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID);} ++ if (!statComm){statComm.reload(streamName, getConnectedBinHost(), JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "");} + if (statComm){ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +diff --git a/src/input/input_rtsp.cpp b/src/input/input_rtsp.cpp +index ebb812e1..25be6e23 100644 +--- a/src/input/input_rtsp.cpp ++++ b/src/input/input_rtsp.cpp +@@ -210,7 +210,7 @@ namespace Mist{ + if (lastSecs != currSecs){ + lastSecs = currSecs; + // Connect to stats for INPUT detection +- statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID); ++ statComm.reload(streamName, getConnectedBinHost(), JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), ""); + if (statComm){ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -225,7 +225,6 @@ namespace Mist{ + statComm.setDown(tcpCon.dataDown()); + statComm.setTime(now - startTime); + statComm.setLastSecond(0); +- statComm.setHost(getConnectedBinHost()); + } + } + } +diff --git a/src/input/input_sdp.cpp b/src/input/input_sdp.cpp +index 3169a836..0b8ddeb5 100644 +--- a/src/input/input_sdp.cpp ++++ b/src/input/input_sdp.cpp +@@ -202,7 +202,7 @@ namespace Mist{ + if (lastSecs != currSecs){ + lastSecs = currSecs; + // Connect to stats for INPUT detection +- statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID); ++ statComm.reload(streamName, getConnectedBinHost(), JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), ""); + if (statComm){ + if (statComm.getStatus() == COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -217,7 +217,6 @@ namespace Mist{ + statComm.setUp(bytesUp); + statComm.setTime(now - startTime); + statComm.setLastSecond(0); +- statComm.setHost(getConnectedBinHost()); + } + } + // If the error flag is raised or we are lacking data, try to recover +diff --git a/src/input/input_ts.cpp b/src/input/input_ts.cpp +index 23311dc0..e405e3b6 100644 +--- a/src/input/input_ts.cpp ++++ b/src/input/input_ts.cpp +@@ -621,7 +621,7 @@ namespace Mist{ + // Check for and spawn threads here. + if (Util::bootSecs() - threadCheckTimer > 1){ + // Connect to stats for INPUT detection +- statComm.reload(streamName, "", JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), "", SESS_BUNDLE_STREAMNAME_HOSTNAME_SESSIONID); ++ statComm.reload(streamName, getConnectedBinHost(), JSON::Value(getpid()).asString(), "INPUT:" + capa["name"].asStringRef(), ""); + if (statComm){ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + config->is_active = false; +@@ -636,7 +636,6 @@ namespace Mist{ + statComm.setDown(downCounter + tcpCon.dataDown()); + statComm.setTime(now - startTime); + statComm.setLastSecond(0); +- statComm.setHost(getConnectedBinHost()); + } + + std::set<size_t> activeTracks = liveStream.getActiveTracks(); +diff --git a/src/input/input_tsrist.cpp b/src/input/input_tsrist.cpp +index 5b95aa9f..df658da1 100644 +--- a/src/input/input_tsrist.cpp ++++ b/src/input/input_tsrist.cpp +@@ -284,7 +284,7 @@ namespace Mist{ + } + + +- void inputTSRIST::connStats(Comms::Statistics &statComm){ ++ void inputTSRIST::connStats(Comms::Connections &statComm){ + statComm.setUp(0); + statComm.setDown(downBytes); + statComm.setHost(getConnectedBinHost()); +diff --git a/src/input/input_tsrist.h b/src/input/input_tsrist.h +index 731f9b04..a75f6601 100644 +--- a/src/input/input_tsrist.h ++++ b/src/input/input_tsrist.h +@@ -30,7 +30,7 @@ namespace Mist{ + int64_t timeStampOffset; + uint64_t lastTimeStamp; + +- virtual void connStats(Comms::Statistics &statComm); ++ virtual void connStats(Comms::Connections &statComm); + + struct rist_ctx *receiver_ctx; + +diff --git a/src/output/output.cpp b/src/output/output.cpp +index 50d67549..d525b8ea 100644 +--- a/src/output/output.cpp ++++ b/src/output/output.cpp +@@ -92,7 +92,7 @@ namespace Mist{ + firstTime = 0; + firstPacketTime = 0xFFFFFFFFFFFFFFFFull; + lastPacketTime = 0; +- sid = ""; ++ tkn = ""; + parseData = false; + wantRequest = true; + sought = false; +@@ -111,7 +111,6 @@ namespace Mist{ + lastPushUpdate = 0; + previousFile = ""; + currentFile = ""; +- sessionMode = 0xFFFFFFFFFFFFFFFFull; + + lastRecv = Util::bootSecs(); + if (myConn){ +@@ -230,7 +229,7 @@ namespace Mist{ + bool Output::isReadyForPlay(){ + // If a protocol does not support any codecs, we assume you know what you're doing + if (!capa.isMember("codecs")){return true;} +- if (!isInitialized){initialize();} ++ if (!isInitialized){return false;} + meta.reloadReplacedPagesIfNeeded(); + if (getSupportedTracks().size()){ + size_t minTracks = 2; +@@ -277,6 +276,7 @@ namespace Mist{ + /// Assumes streamName class member has been set already. + /// Will start input if not currently active, calls onFail() if this does not succeed. + void Output::reconnect(){ ++ Comms::sessionConfigCache(); + thisPacket.null(); + if (config->hasOption("noinput") && config->getBool("noinput")){ + Util::sanitizeName(streamName); +@@ -347,11 +347,10 @@ namespace Mist{ + isInitialized = true; + + //Connect to stats reporting, if not connected already +- if (!statComm){ +- statComm.reload(streamName, getConnectedHost(), sid, capa["name"].asStringRef(), reqUrl, sessionMode); +- stats(true); +- } +- ++ stats(true); ++ //Abort if the stats code shut us down just now ++ if (!isInitialized){return;} ++ + //push inputs do not need to wait for stream to be ready for playback + if (isPushing()){return;} + +@@ -1216,7 +1215,7 @@ namespace Mist{ + /// request URL (if any) + /// ~~~~~~~~~~~~~~~ + int Output::run(){ +- sessionMode = Util::getGlobalConfig("sessionMode").asInt(); ++ Comms::sessionConfigCache(); + /*LTS-START*/ + // Connect to file target, if needed + if (isFileTarget()){ +@@ -1257,6 +1256,7 @@ namespace Mist{ + /*LTS-END*/ + DONTEVEN_MSG("MistOut client handler started"); + while (keepGoing() && (wantRequest || parseData)){ ++ Comms::sessionConfigCache(); + if (wantRequest){requestHandler();} + if (parseData){ + if (!isInitialized){ +@@ -1779,27 +1779,35 @@ namespace Mist{ + } + } + +- if (!statComm){statComm.reload(streamName, getConnectedHost(), sid, capa["name"].asStringRef(), reqUrl, sessionMode);} +- if (!statComm){return;} +- if (statComm.getExit()){ ++ // Disable stats for HTTP internal output ++ if (Comms::sessionStreamInfoMode == SESS_HTTP_DISABLED && capa["name"].asStringRef() == "HTTP"){return;} ++ ++ // Set the token to the pid for outputs which do not generate it in the requestHandler ++ if (!tkn.size()){ tkn = JSON::Value(getpid()).asString(); } ++ ++ if (!statComm){ ++ statComm.reload(streamName, getConnectedBinHost(), tkn, getStatsName(), reqUrl); ++ } ++ if (!statComm || statComm.getExit()){ + onFail("Shutting down since this session is not allowed to view this stream"); ++ statComm.unload(); + return; +- } ++ } + + lastStats = now; + + VERYHIGH_MSG("Writing stats: %s, %s, %s, %" PRIu64 ", %" PRIu64, getConnectedHost().c_str(), streamName.c_str(), +- sid.c_str(), myConn.dataUp(), myConn.dataDown()); ++ tkn.c_str(), myConn.dataUp(), myConn.dataDown()); + /*LTS-START*/ + if (statComm.getStatus() & COMM_STATUS_REQDISCONNECT){ + onFail("Shutting down on controller request"); ++ statComm.unload(); + return; + } + /*LTS-END*/ + statComm.setNow(now); +- statComm.setConnector(getStatsName()); + connStats(now, statComm); +- statComm.setLastSecond(thisPacket ? thisPacket.getTime() : 0); ++ statComm.setLastSecond(thisPacket ? thisPacket.getTime()/1000 : 0); + statComm.setPid(getpid()); + + /*LTS-START*/ +diff --git a/src/output/output.h b/src/output/output.h +index 173b3840..441c06ab 100644 +--- a/src/output/output.h ++++ b/src/output/output.h +@@ -130,8 +130,7 @@ namespace Mist{ + + Comms::Connections statComm; + bool isBlocking; ///< If true, indicates that myConn is blocking. +- std::string sid; ///< Random identifier used to split connections into sessions +- uint64_t sessionMode; ++ std::string tkn; ///< Random identifier used to split connections into sessions + uint64_t nextKeyTime(); + + // stream delaying variables +diff --git a/src/output/output_cmaf.cpp b/src/output/output_cmaf.cpp +index c2fbc5bc..eb7c87da 100644 +--- a/src/output/output_cmaf.cpp ++++ b/src/output/output_cmaf.cpp +@@ -222,24 +222,17 @@ namespace Mist{ + void OutCMAF::sendHlsMasterManifest(){ + selectDefaultTracks(); + +- std::string sessId = ""; +- if (hasSessionIDs()){ +- std::string ua = UA + JSON::Value(getpid()).asString(); +- crc = checksum::crc32(0, ua.data(), ua.size()); +- sessId = JSON::Value(crc).asString(); +- } +- + // check for forced "no low latency" parameter + bool noLLHLS = H.GetVar("llhls").size() ? H.GetVar("llhls") == "0" : false; + + // Populate the struct that will help generate the master playlist + const HLS::MasterData masterData ={ +- hasSessionIDs(), ++ false,//hasSessionIDs, unused + noLLHLS, + hlsMediaFormat == ".ts", + getMainSelectedTrack(), + H.GetHeader("User-Agent"), +- sessId, ++ (Comms::tknMode & 0x04)?tkn:"", + systemBoot, + bootMsOffset, + }; +@@ -261,11 +254,8 @@ namespace Mist{ + + // Chunkpath & Session ID logic + std::string urlPrefix = ""; +- std::string sessId = ""; + if (config->getString("chunkpath").size()){ + urlPrefix = HTTP::URL(config->getString("chunkpath")).link("./" + H.url).link("./").getUrl(); +- }else{ +- sessId = H.GetVar("sessId"); + } + + // check for forced "no low latency" parameter +@@ -279,7 +269,7 @@ namespace Mist{ + noLLHLS, + hlsMediaFormat, + M.getEncryption(requestTid), +- sessId, ++ (Comms::tknMode & 0x04)?tkn:"", + timingTid, + requestTid, + M.biggestFragment(timingTid) / 1000, +@@ -346,6 +336,16 @@ namespace Mist{ + std::string url = H.url.substr(H.url.find('/', 6) + 1); + HTTP::URL req(reqUrl); + ++ ++ if (tkn.size()){ ++ if (Comms::tknMode & 0x08){ ++ const std::string koekjes = H.GetHeader("Cookie"); ++ std::stringstream cookieHeader; ++ cookieHeader << "tkn=" << tkn << "; Max-Age=" << SESS_TIMEOUT; ++ H.SetHeader("Set-Cookie", cookieHeader.str()); ++ } ++ } ++ + // Send a dash manifest for any URL with .mpd in the path + if (req.getExt() == "mpd"){ + sendDashManifest(); +@@ -438,6 +438,7 @@ namespace Mist{ + H.SendResponse("400", "Bad Request: Could not parse the url", myConn); + return; + } ++ + std::string headerData = + CMAF::keyHeader(M, idx, startTime, targetTime, fragmentIndex, false, false); + +diff --git a/src/output/output_hls.cpp b/src/output/output_hls.cpp +index ad810aa7..112e7ee2 100644 +--- a/src/output/output_hls.cpp ++++ b/src/output/output_hls.cpp +@@ -11,7 +11,7 @@ const std::string hlsMediaFormat = ".ts"; + + namespace Mist{ + bool OutHLS::isReadyForPlay(){ +- if (!isInitialized){initialize();} ++ if (!isInitialized){return false;} + meta.reloadReplacedPagesIfNeeded(); + if (!M.getValidTracks().size()){return false;} + uint32_t mainTrack = M.mainTrack(); +@@ -110,25 +110,17 @@ namespace Mist{ + ///\return The master playlist file for (LL)HLS. + void OutHLS::sendHlsMasterManifest(){ + selectDefaultTracks(); +- +- std::string sessId = ""; +- if (hasSessionIDs()){ +- std::string ua = UA + JSON::Value(getpid()).asString(); +- crc = checksum::crc32(0, ua.data(), ua.size()); +- sessId = JSON::Value(crc).asString(); +- } +- + // check for forced "no low latency" parameter + bool noLLHLS = H.GetVar("llhls").size() ? H.GetVar("llhls") == "0" : false; + + // Populate the struct that will help generate the master playlist + const HLS::MasterData masterData ={ +- hasSessionIDs(), ++ false,//hasSessionIDs, unused + noLLHLS, + hlsMediaFormat == ".ts", + getMainSelectedTrack(), + H.GetHeader("User-Agent"), +- sessId, ++ (Comms::tknMode & 0x04)?tkn:"", + systemBoot, + bootMsOffset, + }; +@@ -150,11 +142,8 @@ namespace Mist{ + + // Chunkpath & Session ID logic + std::string urlPrefix = ""; +- std::string sessId = ""; + if (config->getString("chunkpath").size()){ + urlPrefix = HTTP::URL(config->getString("chunkpath")).link("./" + H.url).link("./").getUrl(); +- }else{ +- sessId = H.GetVar("sessId"); + } + + // check for forced "no low latency" parameter +@@ -168,7 +157,7 @@ namespace Mist{ + noLLHLS, + hlsMediaFormat, + M.getEncryption(requestTid), +- sessId, ++ (Comms::tknMode & 0x04)?tkn:"", + timingTid, + requestTid, + M.biggestFragment(timingTid) / 1000, +@@ -226,6 +215,15 @@ namespace Mist{ + bootMsOffset = 0; + if (M.getLive()){bootMsOffset = M.getBootMsOffset();} + ++ if (tkn.size()){ ++ if (Comms::tknMode & 0x08){ ++ const std::string koekjes = H.GetHeader("Cookie"); ++ std::stringstream cookieHeader; ++ cookieHeader << "tkn=" << tkn << "; Max-Age=" << SESS_TIMEOUT; ++ H.SetHeader("Set-Cookie", cookieHeader.str()); ++ } ++ } ++ + if (H.url == "/crossdomain.xml"){ + H.SetHeader("Content-Type", "text/xml"); + H.SetHeader("Server", APPIDENT); +diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp +index f55b974d..ed8fa33b 100644 +--- a/src/output/output_http.cpp ++++ b/src/output/output_http.cpp +@@ -217,7 +217,9 @@ namespace Mist{ + myConn.close(); + return; + } +- if (handler != capa["name"].asStringRef() || H.GetVar("stream") != streamName){ ++ ++ //Check if we need to change binary and/or reconnect ++ if (handler != capa["name"].asStringRef() || H.GetVar("stream") != streamName || (statComm && (statComm.getHost() != getConnectedBinHost() || statComm.getTkn() != tkn))){ + MEDIUM_MSG("Switching from %s (%s) to %s (%s)", capa["name"].asStringRef().c_str(), + streamName.c_str(), handler.c_str(), H.GetVar("stream").c_str()); + streamName = H.GetVar("stream"); +@@ -268,21 +270,32 @@ namespace Mist{ + realTime = 0; + } + } +- // Get session ID cookie or generate a random one if it wasn't set +- if (!sid.size()){ ++ // Read the session token ++ if (Comms::tknMode & 0x01){ ++ // Get session token from the request url ++ if (H.GetVar("tkn") != ""){ ++ tkn = H.GetVar("tkn"); ++ } else if (H.GetVar("sid") != ""){ ++ tkn = H.GetVar("sid"); ++ } else if (H.GetVar("sessId") != ""){ ++ tkn = H.GetVar("sessId"); ++ } ++ } ++ if ((Comms::tknMode & 0x02) && !tkn.size()){ ++ // Get session token from the request cookie + std::map<std::string, std::string> storage; + const std::string koekjes = H.GetHeader("Cookie"); +- HTTP::parseVars(koekjes, storage); +- if (storage.count("sid")){ +- // Get sid cookie, which is used to divide connections into sessions +- sid = storage.at("sid"); +- }else{ +- // Else generate one +- const std::string newSid = UA + JSON::Value(getpid()).asString(); +- sid = JSON::Value(checksum::crc32(0, newSid.data(), newSid.size())).asString(); +- H.SetHeader("sid", sid.c_str()); ++ HTTP::parseVars(koekjes, storage, "; "); ++ if (storage.count("tkn")){ ++ tkn = storage.at("tkn"); + } + } ++ // Generate a session token if it is being sent as a cookie or url parameter and we couldn't read one ++ if (!tkn.size() && Comms::tknMode > 3){ ++ const std::string newTkn = UA + JSON::Value(getpid()).asString(); ++ tkn = JSON::Value(checksum::crc32(0, newTkn.data(), newTkn.size())).asString(); ++ HIGH_MSG("Generated tkn '%s'", tkn.c_str()); ++ } + // Handle upgrade to websocket if the output supports it + std::string upgradeHeader = H.GetHeader("Upgrade"); + Util::stringToLower(upgradeHeader); +@@ -290,7 +303,9 @@ namespace Mist{ + INFO_MSG("Switching to Websocket mode"); + setBlocking(false); + preWebsocketConnect(); +- webSock = new HTTP::Websocket(myConn, H); ++ HTTP::Parser req = H; ++ H.Clean(); ++ webSock = new HTTP::Websocket(myConn, req, H); + if (!(*webSock)){ + delete webSock; + webSock = 0; +@@ -333,6 +348,14 @@ namespace Mist{ + void HTTPOutput::respondHTTP(const HTTP::Parser & req, bool headersOnly){ + //We generally want the CORS headers to be set for all responses + H.setCORSHeaders(); ++ H.SetHeader("Server", APPIDENT); ++ if (tkn.size()){ ++ if (Comms::tknMode & 0x08){ ++ std::stringstream cookieHeader; ++ cookieHeader << "tkn=" << tkn << "; Max-Age=" << SESS_TIMEOUT; ++ H.SetHeader("Set-Cookie", cookieHeader.str()); ++ } ++ } + //Set attachment header to force download, if applicable + if (req.GetVar("dl").size()){ + //If we want to download, and the string contains a dot, use as-is. +@@ -395,6 +418,8 @@ namespace Mist{ + ///\brief Handles requests by starting a corresponding output process. + ///\param connector The type of connector to be invoked. + void HTTPOutput::reConnector(std::string &connector){ ++ // Clear tkn in order to deal with reverse proxies ++ tkn = ""; + // taken from CheckProtocols (controller_connectors.cpp) + char *argarr[32]; + for (int i = 0; i < 32; i++){argarr[i] = 0;} +diff --git a/src/output/output_http_internal.cpp b/src/output/output_http_internal.cpp +index 97ca455f..be955196 100644 +--- a/src/output/output_http_internal.cpp ++++ b/src/output/output_http_internal.cpp +@@ -76,11 +76,11 @@ namespace Mist{ + std::string method = H.method; + // send logo icon + if (H.url.length() > 4 && H.url.substr(H.url.length() - 4, 4) == ".ico"){ +- sendIcon(); ++ sendIcon(false); + return; + } + if (H.url.length() > 6 && H.url.substr(H.url.length() - 5, 5) == ".html"){ +- HTMLResponse(); ++ HTMLResponse(H, false); + return; + } + if (H.url.size() >= 3 && H.url.substr(H.url.size() - 3) == ".js"){ +@@ -337,9 +337,9 @@ namespace Mist{ + } + } + +- void OutHTTP::HTMLResponse(){ +- std::string method = H.method; +- HTTP::URL fullURL(H.GetHeader("Host")); ++ void OutHTTP::HTMLResponse(const HTTP::Parser & req, bool headersOnly){ ++ HTTPOutput::respondHTTP(req, headersOnly); ++ HTTP::URL fullURL(req.GetHeader("Host")); + if (!fullURL.protocol.size()){fullURL.protocol = getProtocolForPort(fullURL.getPort());} + if (config->getString("pubaddr") != ""){ + HTTP::URL altURL(config->getString("pubaddr")); +@@ -349,24 +349,22 @@ namespace Mist{ + fullURL.path = altURL.path; + } + if (mistPath.size()){fullURL = mistPath;} +- std::string uAgent = H.GetHeader("User-Agent"); ++ std::string uAgent = req.GetHeader("User-Agent"); + + std::string forceType = ""; + if (H.GetVar("forcetype").size()){ +- forceType = ",forceType:\"" + H.GetVar("forcetype") + "\""; ++ forceType = ",forceType:\"" + req.GetVar("forcetype") + "\""; + } + + std::string devSkin = ""; +- if (H.GetVar("dev").size()){devSkin = ",skin:\"dev\"";} +- H.SetVar("stream", ""); +- H.SetVar("dev", ""); ++ if (req.GetVar("dev").size()){devSkin = ",skin:\"dev\"";} + devSkin += ",urlappend:\"" + H.allVars() + "\""; + H.SetVar("stream", streamName); + + std::string seekTo = ""; +- if (H.GetVar("t").size()){ ++ if (req.GetVar("t").size()){ + uint64_t autoSeekTime = 0; +- std::string sTime = H.GetVar("t"); ++ std::string sTime = req.GetVar("t"); + unsigned long long h = 0, m = 0, s = 0; + autoSeekTime = JSON::Value(sTime).asInt(); + if (sscanf(sTime.c_str(), "%llum%llus", &m, &s) == 2){autoSeekTime = m * 60 + s;} +@@ -385,13 +383,10 @@ namespace Mist{ + streamName + "\").addEventListener(\"initialized\",f);"; + } + } +- +- H.Clean(); ++ + H.SetHeader("Content-Type", "text/html"); + H.SetHeader("X-UA-Compatible", "IE=edge"); +- H.SetHeader("Server", APPIDENT); +- H.setCORSHeaders(); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -427,6 +422,7 @@ namespace Mist{ + } + H.SendResponse("200", "OK", myConn); + responded = true; ++ H.Clean(); + } + + JSON::Value OutHTTP::getStatusJSON(std::string &reqHost, const std::string &useragent){ +@@ -634,23 +630,31 @@ namespace Mist{ + + // loop over the added sources, add them to json_resp["sources"] + for (std::set<JSON::Value, sourceCompare>::iterator it = sources.begin(); it != sources.end(); it++){ +- if ((*it)["simul_tracks"].asInt() > 0){json_resp["source"].append(*it);} ++ if ((*it)["simul_tracks"].asInt() > 0){ ++ if (Comms::tknMode & 0x04){ ++ JSON::Value tmp; ++ tmp = (*it); ++ tmp["url"] = tmp["url"].asStringRef() + "?tkn=" + tkn; ++ tmp["relurl"] = tmp["relurl"].asStringRef() + "?tkn=" + tkn; ++ json_resp["source"].append(tmp); ++ }else{ ++ json_resp["source"].append(*it); ++ } ++ } + } + return json_resp; + } + +- void OutHTTP::onHTTP(){ ++ void OutHTTP::respondHTTP(const HTTP::Parser & req, bool headersOnly){ + origStreamName = streamName; +- std::string method = H.method; + +- if (H.GetHeader("X-Mst-Path").size()){mistPath = H.GetHeader("X-Mst-Path");} ++ if (req.GetHeader("X-Mst-Path").size()){mistPath = req.GetHeader("X-Mst-Path");} + + // Handle certbot validations +- if (H.url.substr(0, 28) == "/.well-known/acme-challenge/"){ ++ if (req.url.substr(0, 28) == "/.well-known/acme-challenge/"){ + std::string cbToken = H.url.substr(28); + jsonForEach(config->getOption("certbot", true), it){ + if (it->asStringRef().substr(0, cbToken.size() + 1) == cbToken + ":"){ +- H.Clean(); + H.SetHeader("Content-Type", "text/plain"); + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); +@@ -661,9 +665,7 @@ namespace Mist{ + return; + } + } +- H.Clean(); + H.SetHeader("Content-Type", "text/plain"); +- H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); + H.SetBody("No matching validation found for token '" + cbToken + "'"); + H.SendResponse("404", "Not found", myConn); +@@ -672,12 +674,11 @@ namespace Mist{ + return; + } + +- if (H.url == "/crossdomain.xml"){ +- H.Clean(); ++ if (req.url == "/crossdomain.xml"){ + H.SetHeader("Content-Type", "text/xml"); + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -693,12 +694,11 @@ namespace Mist{ + return; + }// crossdomain.xml + +- if (H.url == "/clientaccesspolicy.xml"){ +- H.Clean(); ++ if (req.url == "/clientaccesspolicy.xml"){ + H.SetHeader("Content-Type", "text/xml"); + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -716,8 +716,7 @@ namespace Mist{ + return; + }// clientaccesspolicy.xml + +- if (H.url == "/flashplayer.swf"){ +- H.Clean(); ++ if (req.url == "/flashplayer.swf"){ + H.SetHeader("Content-Type", "application/x-shockwave-flash"); + H.SetHeader("Server", APPIDENT); + H.SetBody((const char *)FlashMediaPlayback_101_swf, FlashMediaPlayback_101_swf_len); +@@ -725,8 +724,7 @@ namespace Mist{ + responded = true; + return; + } +- if (H.url == "/oldflashplayer.swf"){ +- H.Clean(); ++ if (req.url == "/oldflashplayer.swf"){ + H.SetHeader("Content-Type", "application/x-shockwave-flash"); + H.SetHeader("Server", APPIDENT); + H.SetBody((const char *)FlashMediaPlayback_swf, FlashMediaPlayback_swf_len); +@@ -735,20 +733,21 @@ namespace Mist{ + return; + } + // send logo icon +- if (H.url.length() > 4 && H.url.substr(H.url.length() - 4, 4) == ".ico"){ +- sendIcon(); ++ if (req.url.length() > 4 && req.url.substr(req.url.length() - 4, 4) == ".ico"){ ++ sendIcon(headersOnly); + return; + } + + // send generic HTML page +- if (H.url.length() > 6 && H.url.substr(H.url.length() - 5, 5) == ".html"){ +- HTMLResponse(); ++ if (req.url.length() > 6 && req.url.substr(req.url.length() - 5, 5) == ".html"){ ++ HTMLResponse(req, headersOnly); + return; + } + + // send smil MBR index +- if (H.url.length() > 6 && H.url.substr(H.url.length() - 5, 5) == ".smil"){ +- std::string reqHost = HTTP::URL(H.GetHeader("Host")).host; ++ if (req.url.length() > 6 && req.url.substr(req.url.length() - 5, 5) == ".smil"){ ++ HTTPOutput::respondHTTP(req, headersOnly); ++ std::string reqHost = HTTP::URL(req.GetHeader("Host")).host; + std::string port, url_rel; + std::string trackSources; // this string contains all track sources for MBR smil + { +@@ -782,11 +781,8 @@ namespace Mist{ + } + } + +- H.Clean(); + H.SetHeader("Content-Type", "application/smil"); +- H.SetHeader("Server", APPIDENT); +- H.setCORSHeaders(); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -800,24 +796,22 @@ namespace Mist{ + return; + } + +- if ((H.url.length() > 9 && H.url.substr(0, 6) == "/info_" && H.url.substr(H.url.length() - 3, 3) == ".js") || +- (H.url.length() > 9 && H.url.substr(0, 6) == "/json_" && H.url.substr(H.url.length() - 3, 3) == ".js")){ +- if (websocketHandler()){return;} +- std::string reqHost = HTTP::URL(H.GetHeader("Host")).host; +- std::string useragent = H.GetVar("ua"); +- if (!useragent.size()){useragent = H.GetHeader("User-Agent");} ++ if ((req.url.length() > 9 && req.url.substr(0, 6) == "/info_" && req.url.substr(req.url.length() - 3, 3) == ".js") || ++ (req.url.length() > 9 && req.url.substr(0, 6) == "/json_" && req.url.substr(req.url.length() - 3, 3) == ".js")){ ++ HTTPOutput::respondHTTP(req, headersOnly); ++ if (websocketHandler(req, headersOnly)){return;} ++ std::string reqHost = HTTP::URL(req.GetHeader("Host")).host; ++ std::string useragent = req.GetVar("ua"); ++ if (!useragent.size()){useragent = req.GetHeader("User-Agent");} + std::string response; +- std::string rURL = H.url; +- if (method != "OPTIONS" && method != "HEAD"){initialize();} +- H.Clean(); +- H.SetHeader("Server", APPIDENT); +- H.setCORSHeaders(); ++ std::string rURL = req.url; ++ if (headersOnly){initialize();} + if (rURL.substr(0, 6) != "/json_"){ + H.SetHeader("Content-Type", "application/javascript"); + }else{ + H.SetHeader("Content-Type", "application/json"); + } +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -837,9 +831,9 @@ namespace Mist{ + return; + }// embed code generator + +- if ((H.url == "/player.js") || ((H.url.substr(0, 7) == "/embed_") && (H.url.length() > 10) && +- (H.url.substr(H.url.length() - 3, 3) == ".js"))){ +- HTTP::URL fullURL(H.GetHeader("Host")); ++ if ((req.url == "/player.js") || ((req.url.substr(0, 7) == "/embed_") && (req.url.length() > 10) && ++ (req.url.substr(H.url.length() - 3, 3) == ".js"))){ ++ HTTP::URL fullURL(req.GetHeader("Host")); + if (!fullURL.protocol.size()){fullURL.protocol = getProtocolForPort(fullURL.getPort());} + if (config->getString("pubaddr") != ""){ + HTTP::URL altURL(config->getString("pubaddr")); +@@ -850,12 +844,17 @@ namespace Mist{ + } + if (mistPath.size()){fullURL = mistPath;} + std::string response; +- std::string rURL = H.url; +- H.Clean(); ++ std::string rURL = req.url; ++ ++ if ((rURL.substr(0, 7) == "/embed_") && (rURL.length() > 10) && ++ (rURL.substr(rURL.length() - 3, 3) == ".js")){ ++ HTTPOutput::respondHTTP(req, headersOnly); ++ } ++ + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript; charset=utf-8"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -933,14 +932,13 @@ namespace Mist{ + return; + } + +- if (H.url.substr(0, 7) == "/skins/"){ ++ if (req.url.substr(0, 7) == "/skins/"){ + std::string response; +- std::string url = H.url; +- H.Clean(); ++ std::string url = req.url; + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "text/css"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -970,13 +968,12 @@ namespace Mist{ + H.Clean(); + return; + } +- if (H.url == "/videojs.js"){ ++ if (req.url == "/videojs.js"){ + std::string response; +- H.Clean(); + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -992,13 +989,12 @@ namespace Mist{ + H.Clean(); + return; + } +- if (H.url == "/dashjs.js"){ ++ if (req.url == "/dashjs.js"){ + std::string response; +- H.Clean(); + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -1016,13 +1012,12 @@ namespace Mist{ + H.Clean(); + return; + } +- if (H.url == "/webrtc.js"){ ++ if (req.url == "/webrtc.js"){ + std::string response; +- H.Clean(); + H.SetHeader("Server", APPIDENT); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -1038,13 +1033,12 @@ namespace Mist{ + H.Clean(); + return; + } +- if (H.url == "/flv.js"){ ++ if (req.url == "/flv.js"){ + std::string response; +- H.Clean(); + H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; +@@ -1058,13 +1052,12 @@ namespace Mist{ + H.Clean(); + return; + } +- if (H.url == "/hlsjs.js"){ ++ if (req.url == "/hlsjs.js"){ + std::string response; +- H.Clean(); + H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; +@@ -1084,7 +1077,7 @@ namespace Mist{ + H.SetHeader("Server", "MistServer/" PACKAGE_VERSION); + H.setCORSHeaders(); + H.SetHeader("Content-Type", "application/javascript"); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + H.Clean(); + return; +@@ -1100,15 +1093,13 @@ namespace Mist{ + } + } + +- void OutHTTP::sendIcon(){ +- std::string method = H.method; +- H.Clean(); ++ void OutHTTP::sendIcon(bool headersOnly){ + #include "../icon.h" + H.SetHeader("Content-Type", "image/x-icon"); + H.SetHeader("Server", APPIDENT); + H.SetHeader("Content-Length", icon_len); + H.setCORSHeaders(); +- if (method == "OPTIONS" || method == "HEAD"){ ++ if (headersOnly){ + H.SendResponse("200", "OK", myConn); + responded = true; + H.Clean(); +@@ -1120,16 +1111,16 @@ namespace Mist{ + H.Clean(); + } + +- bool OutHTTP::websocketHandler(){ ++ bool OutHTTP::websocketHandler(const HTTP::Parser & req, bool headersOnly){ + stayConnected = true; +- std::string reqHost = HTTP::URL(H.GetHeader("Host")).host; +- if (H.GetHeader("X-Mst-Path").size()){mistPath = H.GetHeader("X-Mst-Path");} +- std::string useragent = H.GetVar("ua"); +- if (!useragent.size()){useragent = H.GetHeader("User-Agent");} +- std::string upgradeHeader = H.GetHeader("Upgrade"); ++ std::string reqHost = HTTP::URL(req.GetHeader("Host")).host; ++ if (req.GetHeader("X-Mst-Path").size()){mistPath = req.GetHeader("X-Mst-Path");} ++ std::string useragent = req.GetVar("ua"); ++ if (!useragent.size()){useragent = req.GetHeader("User-Agent");} ++ std::string upgradeHeader = req.GetHeader("Upgrade"); + Util::stringToLower(upgradeHeader); + if (upgradeHeader != "websocket"){return false;} +- HTTP::Websocket ws(myConn, H); ++ HTTP::Websocket ws(myConn, req, H); + if (!ws){return false;} + setBlocking(false); + // start the stream, if needed +diff --git a/src/output/output_http_internal.h b/src/output/output_http_internal.h +index 774eb186..8e610145 100644 +--- a/src/output/output_http_internal.h ++++ b/src/output/output_http_internal.h +@@ -10,10 +10,10 @@ namespace Mist{ + virtual void onFail(const std::string &msg, bool critical = false); + /// preHTTP is disabled in the internal HTTP output, since most don't need the stream alive to work + virtual void preHTTP(){}; +- void HTMLResponse(); +- void onHTTP(); +- void sendIcon(); +- bool websocketHandler(); ++ void HTMLResponse(const HTTP::Parser & req, bool headersOnly); ++ void respondHTTP(const HTTP::Parser & req, bool headersOnly); ++ void sendIcon(bool headersOnly); ++ bool websocketHandler(const HTTP::Parser & req, bool headersOnly); + JSON::Value getStatusJSON(std::string &reqHost, const std::string &useragent = ""); + bool stayConnected; + virtual bool onFinish(){return stayConnected;} +diff --git a/src/output/output_sdp.cpp b/src/output/output_sdp.cpp +index 6baf9067..50d491e8 100644 +--- a/src/output/output_sdp.cpp ++++ b/src/output/output_sdp.cpp +@@ -141,6 +141,18 @@ namespace Mist{ + } + } + ++ std::string OutSDP::getConnectedHost(){ ++ if (!sdpState.tracks.size()) { return Output::getConnectedHost(); } ++ std::string hostname; ++ uint32_t port; ++ sdpState.tracks[0].data.GetDestination(hostname, port); ++ return hostname; ++ } ++ std::string OutSDP::getConnectedBinHost(){ ++ if (!sdpState.tracks.size()) { return Output::getConnectedBinHost(); } ++ return sdpState.tracks[0].data.getBinDestination(); ++ } ++ + void OutSDP::sendNext(){ + char *dataPointer = 0; + size_t dataLen = 0; +diff --git a/src/output/output_sdp.h b/src/output/output_sdp.h +index 2d4b3368..6c466753 100644 +--- a/src/output/output_sdp.h ++++ b/src/output/output_sdp.h +@@ -16,6 +16,8 @@ namespace Mist{ + void sendNext(); + void sendHeader(); + bool onFinish(); ++ std::string getConnectedHost(); ++ std::string getConnectedBinHost(); + + private: + void initTracks(uint32_t & port, std::string targetIP); +diff --git a/src/output/output_ts.cpp b/src/output/output_ts.cpp +index 561bf9aa..bf46663b 100644 +--- a/src/output/output_ts.cpp ++++ b/src/output/output_ts.cpp +@@ -239,6 +239,18 @@ namespace Mist{ + } + } + ++ std::string OutTS::getConnectedHost(){ ++ if (!pushOut) { return Output::getConnectedHost(); } ++ std::string hostname; ++ uint32_t port; ++ pushSock.GetDestination(hostname, port); ++ return hostname; ++ } ++ std::string OutTS::getConnectedBinHost(){ ++ if (!pushOut) { return Output::getConnectedBinHost(); } ++ return pushSock.getBinDestination(); ++ } ++ + bool OutTS::listenMode(){return !(config->getString("target").size());} + + void OutTS::onRequest(){ +diff --git a/src/output/output_ts.h b/src/output/output_ts.h +index 32aa6958..0c38cc70 100644 +--- a/src/output/output_ts.h ++++ b/src/output/output_ts.h +@@ -12,6 +12,8 @@ namespace Mist{ + virtual void initialSeek(); + bool isReadyForPlay(); + void onRequest(); ++ std::string getConnectedHost(); ++ std::string getConnectedBinHost(); + + private: + size_t udpSize; +diff --git a/src/output/output_tsrist.cpp b/src/output/output_tsrist.cpp +index c4e03f80..10b29673 100644 +--- a/src/output/output_tsrist.cpp ++++ b/src/output/output_tsrist.cpp +@@ -178,6 +178,20 @@ namespace Mist{ + } + + OutTSRIST::~OutTSRIST(){} ++ ++ std::string OutTSRIST::getConnectedHost(){ ++ if (!pushOut) { return Output::getConnectedHost(); } ++ return target.host; ++ } ++ std::string OutTSRIST::getConnectedBinHost(){ ++ if (!pushOut) { return Output::getConnectedBinHost(); } ++ std::string binHost = Socket::getBinForms(target.host); ++ if (binHost.size() > 16){ binHost = binHost.substr(0, 16); } ++ if (binHost.size() < 16){ ++ binHost = std::string("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", 16); ++ } ++ return binHost; ++ } + + void OutTSRIST::init(Util::Config *cfg){ + Output::init(cfg); +@@ -319,7 +333,7 @@ namespace Mist{ + } + } + +- void OutTSRIST::connStats(uint64_t now, Comms::Statistics &statComm){ ++ void OutTSRIST::connStats(uint64_t now, Comms::Connections &statComm){ + if (!myConn){return;} + statComm.setUp(upBytes); + statComm.setDown(0); +diff --git a/src/output/output_tsrist.h b/src/output/output_tsrist.h +index c9a5db39..80ee2376 100644 +--- a/src/output/output_tsrist.h ++++ b/src/output/output_tsrist.h +@@ -16,9 +16,11 @@ namespace Mist{ + bool isReadyForPlay(){return true;} + virtual void requestHandler(); + static void listener(Util::Config &conf, int (*callback)(Socket::Connection &S)); ++ std::string getConnectedHost(); ++ std::string getConnectedBinHost(); + + protected: +- virtual void connStats(uint64_t now, Comms::Statistics &statComm); ++ virtual void connStats(uint64_t now, Comms::Connections &statComm); + //virtual std::string getConnectedHost(){ + // return srtConn.remotehost; + //} +diff --git a/src/session.cpp b/src/session.cpp +index 3865e0ec..d2331c53 100644 +--- a/src/session.cpp ++++ b/src/session.cpp +@@ -7,17 +7,31 @@ + #include <mist/triggers.h> + #include <signal.h> + #include <stdio.h> +-// Stats of connections which have closed are added to these global counters +-uint64_t globalNow = 0; ++ ++// Global counters ++uint64_t now = Util::bootSecs(); ++uint64_t currentConnections = 0; ++uint64_t lastSecond = 0; + uint64_t globalTime = 0; + uint64_t globalDown = 0; + uint64_t globalUp = 0; + uint64_t globalPktcount = 0; + uint64_t globalPktloss = 0; + uint64_t globalPktretrans = 0; ++// Stores last values of each connection ++std::map<size_t, uint64_t> connTime; ++std::map<size_t, uint64_t> connDown; ++std::map<size_t, uint64_t> connUp; ++std::map<size_t, uint64_t> connPktcount; ++std::map<size_t, uint64_t> connPktloss; ++std::map<size_t, uint64_t> connPktretrans; + // Counts the duration a connector has been active + std::map<std::string, uint64_t> connectorCount; + std::map<std::string, uint64_t> connectorLastActive; ++std::map<std::string, uint64_t> hostCount; ++std::map<std::string, uint64_t> hostLastActive; ++std::map<std::string, uint64_t> streamCount; ++std::map<std::string, uint64_t> streamLastActive; + // Set to True when a session gets invalidated, so that we know to run a new USER_NEW trigger + bool forceTrigger = false; + void handleSignal(int signum){ +@@ -26,96 +40,141 @@ void handleSignal(int signum){ + } + } + +-void userOnActive(uint64_t &connections){ +- ++connections; +-} ++const char nullAddress[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +-std::string getEnvWithDefault(const std::string variableName, const std::string defaultValue){ +- const char* value = getenv(variableName.c_str()); +- if (value){ +- unsetenv(variableName.c_str()); +- return value; +- }else{ +- return defaultValue; +- } ++void userOnActive(Comms::Connections &connections, size_t idx){ ++ uint64_t lastUpdate = connections.getNow(idx); ++ if (lastUpdate < now - 10){return;} ++ ++currentConnections; ++ std::string thisConnector = connections.getConnector(idx); ++ std::string thisStreamName = connections.getStream(idx); ++ const std::string& thisHost = connections.getHost(idx); ++ ++ if (connections.getLastSecond(idx) > lastSecond){lastSecond = connections.getLastSecond(idx);} ++ // Save info on the latest active stream, protocol and host separately ++ if (thisConnector.size() && thisConnector != "HTTP"){ ++ connectorCount[thisConnector]++; ++ if (connectorLastActive[thisConnector] < lastUpdate){connectorLastActive[thisConnector] = lastUpdate;} ++ } ++ if (thisStreamName.size()){ ++ streamCount[thisStreamName]++; ++ if (streamLastActive[thisStreamName] < lastUpdate){streamLastActive[thisStreamName] = lastUpdate;} ++ } ++ if (memcmp(thisHost.data(), nullAddress, 16)){ ++ hostCount[thisHost]++; ++ if (!hostLastActive.count(thisHost) || hostLastActive[thisHost] < lastUpdate){hostLastActive[thisHost] = lastUpdate;} ++ } ++ // Sanity checks ++ if (connections.getDown(idx) < connDown[idx]){ ++ WARN_MSG("Connection downloaded bytes should be a counter, but has decreased in value"); ++ connDown[idx] = connections.getDown(idx); ++ } ++ if (connections.getUp(idx) < connUp[idx]){ ++ WARN_MSG("Connection uploaded bytes should be a counter, but has decreased in value"); ++ connUp[idx] = connections.getUp(idx); ++ } ++ if (connections.getPacketCount(idx) < connPktcount[idx]){ ++ WARN_MSG("Connection packet count should be a counter, but has decreased in value"); ++ connPktcount[idx] = connections.getPacketCount(idx); ++ } ++ if (connections.getPacketLostCount(idx) < connPktloss[idx]){ ++ WARN_MSG("Connection packet loss count should be a counter, but has decreased in value"); ++ connPktloss[idx] = connections.getPacketLostCount(idx); ++ } ++ if (connections.getPacketRetransmitCount(idx) < connPktretrans[idx]){ ++ WARN_MSG("Connection packets retransmitted should be a counter, but has decreased in value"); ++ connPktretrans[idx] = connections.getPacketRetransmitCount(idx); ++ } ++ // Add increase in stats to global stats ++ globalDown += connections.getDown(idx) - connDown[idx]; ++ globalUp += connections.getUp(idx) - connUp[idx]; ++ globalPktcount += connections.getPacketCount(idx) - connPktcount[idx]; ++ globalPktloss += connections.getPacketLostCount(idx) - connPktloss[idx]; ++ globalPktretrans += connections.getPacketRetransmitCount(idx) - connPktretrans[idx]; ++ // Set last values of this connection ++ connTime[idx]++; ++ connDown[idx] = connections.getDown(idx); ++ connUp[idx] = connections.getUp(idx); ++ connPktcount[idx] = connections.getPacketCount(idx); ++ connPktloss[idx] = connections.getPacketLostCount(idx); ++ connPktretrans[idx] = connections.getPacketRetransmitCount(idx); + } + +-/// \brief Adds stats of closed connections to global counters ++/// \brief Remove mappings of inactive connections + void userOnDisconnect(Comms::Connections & connections, size_t idx){ +- std::string thisConnector = connections.getConnector(idx); +- if (thisConnector != ""){ +- connectorCount[thisConnector] += connections.getTime(idx); +- } +- globalTime += connections.getTime(idx); +- globalDown += connections.getDown(idx); +- globalUp += connections.getUp(idx); +- globalPktcount += connections.getPacketCount(idx); +- globalPktloss += connections.getPacketLostCount(idx); +- globalPktretrans += connections.getPacketRetransmitCount(idx); ++ connTime.erase(idx); ++ connDown.erase(idx); ++ connUp.erase(idx); ++ connPktcount.erase(idx); ++ connPktloss.erase(idx); ++ connPktretrans.erase(idx); + } + + int main(int argc, char **argv){ + Comms::Connections connections; + Comms::Sessions sessions; + uint64_t lastSeen = Util::bootSecs(); +- uint64_t currentConnections = 0; + Util::redirectLogsIfNeeded(); + signal(SIGUSR1, handleSignal); + // Init config and parse arguments + Util::Config config = Util::Config("MistSession"); + JSON::Value option; ++ char * tmpStr = 0; + + option.null(); + option["arg_num"] = 1; + option["arg"] = "string"; + option["help"] = "Session identifier of the entire session"; +- option["default"] = ""; + config.addOption("sessionid", option); + +- option.null(); +- option["long"] = "sessionmode"; +- option["short"] = "m"; +- option["arg"] = "integer"; +- option["default"] = 0; +- config.addOption("sessionmode", option); +- + option.null(); + option["long"] = "streamname"; +- option["short"] = "n"; ++ option["short"] = "s"; + option["arg"] = "string"; +- option["default"] = ""; ++ option["help"] = "Stream name initial value. May also be passed as SESSION_STREAM"; ++ tmpStr = getenv("SESSION_STREAM"); ++ option["default"] = tmpStr?tmpStr:""; + config.addOption("streamname", option); + + option.null(); + option["long"] = "ip"; + option["short"] = "i"; + option["arg"] = "string"; +- option["default"] = ""; ++ option["help"] = "IP address initial value. May also be passed as SESSION_IP"; ++ tmpStr = getenv("SESSION_IP"); ++ option["default"] = tmpStr?tmpStr:""; + config.addOption("ip", option); + + option.null(); +- option["long"] = "sid"; +- option["short"] = "s"; ++ option["long"] = "tkn"; ++ option["short"] = "t"; + option["arg"] = "string"; +- option["default"] = ""; +- config.addOption("sid", option); ++ option["help"] = "Client-side session ID initial value. May also be passed as SESSION_TKN"; ++ tmpStr = getenv("SESSION_TKN"); ++ option["default"] = tmpStr?tmpStr:""; ++ config.addOption("tkn", option); + + option.null(); + option["long"] = "protocol"; + option["short"] = "p"; + option["arg"] = "string"; +- option["default"] = ""; ++ option["help"] = "Protocol initial value. May also be passed as SESSION_PROTOCOL"; ++ tmpStr = getenv("SESSION_PROTOCOL"); ++ option["default"] = tmpStr?tmpStr:""; + config.addOption("protocol", option); + + option.null(); + option["long"] = "requrl"; + option["short"] = "r"; + option["arg"] = "string"; +- option["default"] = ""; ++ option["help"] = "Request URL initial value. May also be passed as SESSION_REQURL"; ++ tmpStr = getenv("SESSION_REQURL"); ++ option["default"] = tmpStr?tmpStr:""; + config.addOption("requrl", option); + + config.activate(); + if (!(config.parseArgs(argc, argv))){ ++ config.printHelp(std::cout); + FAIL_MSG("Cannot start a new session due to invalid arguments"); + return 1; + } +@@ -123,24 +182,17 @@ int main(int argc, char **argv){ + const uint64_t bootTime = Util::getMicros(); + // Get session ID, session mode and other variables used as payload for the USER_NEW and USER_END triggers + const std::string thisStreamName = config.getString("streamname"); +- const std::string thisHost = config.getString("ip"); +- const std::string thisSid = config.getString("sid"); ++ const std::string thisToken = config.getString("tkn"); + const std::string thisProtocol = config.getString("protocol"); + const std::string thisReqUrl = config.getString("requrl"); + const std::string thisSessionId = config.getString("sessionid"); +- const uint64_t sessionMode = config.getInteger("sessionmode"); +- +- if (thisSessionId == "" || thisProtocol == "" || thisStreamName == ""){ +- FAIL_MSG("Given the following incomplete arguments: SessionId: '%s', protocol: '%s', stream name: '%s'. Aborting opening a new session", +- thisSessionId.c_str(), thisProtocol.c_str(), thisStreamName.c_str()); +- return 1; +- } ++ std::string thisHost = Socket::getBinForms(config.getString("ip")); ++ if (thisHost.size() > 16){thisHost = thisHost.substr(0, 16);} + +- MEDIUM_MSG("Starting a new session for sessionId '%s'", thisSessionId.c_str()); +- if (sessionMode < 1 || sessionMode > 15) { +- FAIL_MSG("Invalid session mode of value %lu. Should be larger than 0 and smaller than 16", sessionMode); +- return 1; +- } ++ std::string ipHex; ++ Socket::hostBytesToStr(thisHost.c_str(), thisHost.size(), ipHex); ++ VERYHIGH_MSG("Starting a new session. Passed variables are stream name '%s', session token '%s', protocol '%s', requested URL '%s', IP '%s' and session id '%s'", ++ thisStreamName.c_str(), thisToken.c_str(), thisProtocol.c_str(), thisReqUrl.c_str(), ipHex.c_str(), thisSessionId.c_str()); + + // Try to lock to ensure we are the only process initialising this session + IPC::semaphore sessionLock; +@@ -174,194 +226,200 @@ int main(int argc, char **argv){ + sessionLock.post(); + return 1; + } +- // Open the shared memory page containing statistics for each individual connection in this session +- connections.reload(thisStreamName, thisHost, thisSid, thisProtocol, thisReqUrl, sessionMode, true, false); ++ + // Initialise global session data + sessions.setHost(thisHost); + sessions.setSessId(thisSessionId); + sessions.setStream(thisStreamName); +- sessionLock.post(); ++ if (thisProtocol.size() && thisProtocol != "HTTP"){connectorLastActive[thisProtocol] = now;} ++ if (thisStreamName.size()){streamLastActive[thisStreamName] = now;} ++ if (memcmp(thisHost.data(), nullAddress, 16)){hostLastActive[thisHost] = now;} ++ ++ // Open the shared memory page containing statistics for each individual connection in this session ++ connections.reload(thisSessionId, true); + + // Determine session type, since triggers only get run for viewer type sessions + uint64_t thisType = 0; + if (thisSessionId[0] == 'I'){ +- INFO_MSG("Started new input session %s in %lu microseconds", thisSessionId.c_str(), Util::getMicros(bootTime)); + thisType = 1; +- } +- else if (thisSessionId[0] == 'O'){ +- INFO_MSG("Started new output session %s in %lu microseconds", thisSessionId.c_str(), Util::getMicros(bootTime)); ++ } else if (thisSessionId[0] == 'O'){ + thisType = 2; +- } +- else{ +- INFO_MSG("Started new viewer session %s in %lu microseconds", thisSessionId.c_str(), Util::getMicros(bootTime)); ++ } else if (thisSessionId[0] == 'U'){ ++ thisType = 3; + } + + // Do a USER_NEW trigger if it is defined for this stream + if (!thisType && Triggers::shouldTrigger("USER_NEW", thisStreamName)){ +- std::string payload = thisStreamName + "\n" + thisHost + "\n" + +- thisSid + "\n" + thisProtocol + ++ std::string payload = thisStreamName + "\n" + config.getString("ip") + "\n" + ++ thisToken + "\n" + thisProtocol + + "\n" + thisReqUrl + "\n" + thisSessionId; + if (!Triggers::doTrigger("USER_NEW", payload, thisStreamName)){ + // Mark all connections of this session as finished, since this viewer is not allowed to view this stream ++ Util::logExitReason("Session rejected by USER_NEW"); + connections.setExit(); + connections.finishAll(); + } + } + +- uint64_t lastSecond = 0; +- uint64_t now = 0; +- uint64_t time = 0; +- uint64_t down = 0; +- uint64_t up = 0; +- uint64_t pktcount = 0; +- uint64_t pktloss = 0; +- uint64_t pktretrans = 0; +- std::string connector = ""; ++ //start allowing viewers ++ sessionLock.post(); ++ ++ INFO_MSG("Started new session %s in %.3f ms", thisSessionId.c_str(), (double)Util::getMicros(bootTime)/1000.0); ++ + // Stay active until Mist exits or we no longer have an active connection +- while (config.is_active && (currentConnections || Util::bootSecs() - lastSeen <= 10)){ +- time = 0; +- connector = ""; +- down = 0; +- up = 0; +- pktcount = 0; +- pktloss = 0; +- pktretrans = 0; ++ while (config.is_active && (currentConnections || now - lastSeen <= STATS_DELAY) && !connections.getExit()){ + currentConnections = 0; ++ lastSecond = 0; ++ now = Util::bootSecs(); + +- // Count active connections +- COMM_LOOP(connections, userOnActive(currentConnections), userOnDisconnect(connections, id)); + // Loop through all connection entries to get a summary of statistics +- for (uint64_t idx = 0; idx < connections.recordCount(); idx++){ +- if (connections.getStatus(idx) == COMM_STATUS_INVALID || connections.getStatus(idx) & COMM_STATUS_DISCONNECT){continue;} +- uint64_t thisLastSecond = connections.getLastSecond(idx); +- std::string thisConnector = connections.getConnector(idx); +- // Save info on the latest active connection separately +- if (thisLastSecond > lastSecond){ +- lastSecond = thisLastSecond; +- now = connections.getNow(idx); +- } +- connectorLastActive[thisConnector] = thisLastSecond; +- // Sum all other variables +- time += connections.getTime(idx); +- down += connections.getDown(idx); +- up += connections.getUp(idx); +- pktcount += connections.getPacketCount(idx); +- pktloss += connections.getPacketLostCount(idx); +- pktretrans += connections.getPacketRetransmitCount(idx); ++ COMM_LOOP(connections, userOnActive(connections, id), userOnDisconnect(connections, id)); ++ if (currentConnections){ ++ globalTime++; ++ lastSeen = now; + } + +- // Convert connector duration to string +- std::stringstream connectorSummary; +- bool addDelimiter = false; +- connectorSummary << "{"; +- for (std::map<std::string, uint64_t>::iterator it = connectorLastActive.begin(); +- it != connectorLastActive.end(); ++it){ +- if (lastSecond - it->second < 10000){ +- connectorSummary << (addDelimiter ? "," : "") << it->first; +- addDelimiter = true; +- } +- } +- connectorSummary << "}"; +- +- // Write summary to global statistics +- sessions.setTime(time + globalTime); +- sessions.setDown(down + globalDown); +- sessions.setUp(up + globalUp); +- sessions.setPacketCount(pktcount + globalPktcount); +- sessions.setPacketLostCount(pktloss + globalPktloss); +- sessions.setPacketRetransmitCount(pktretrans + globalPktretrans); ++ ++ sessions.setTime(globalTime); ++ sessions.setDown(globalDown); ++ sessions.setUp(globalUp); ++ sessions.setPacketCount(globalPktcount); ++ sessions.setPacketLostCount(globalPktloss); ++ sessions.setPacketRetransmitCount(globalPktretrans); + sessions.setLastSecond(lastSecond); +- sessions.setConnector(connectorSummary.str()); + sessions.setNow(now); + ++ if (currentConnections){ ++ { ++ // Convert active protocols to string ++ std::stringstream connectorSummary; ++ for (std::map<std::string, uint64_t>::iterator it = connectorLastActive.begin(); ++ it != connectorLastActive.end(); ++it){ ++ if (now - it->second < STATS_DELAY){ ++ connectorSummary << (connectorSummary.str().size() ? "," : "") << it->first; ++ } ++ } ++ sessions.setConnector(connectorSummary.str()); ++ } ++ ++ { ++ // Set active host to last active or 0 if there were various hosts active recently ++ std::string thisHost; ++ for (std::map<std::string, uint64_t>::iterator it = hostLastActive.begin(); ++ it != hostLastActive.end(); ++it){ ++ if (now - it->second < STATS_DELAY){ ++ if (!thisHost.size()){ ++ thisHost = it->first; ++ }else if (thisHost != it->first){ ++ thisHost = nullAddress; ++ break; ++ } ++ } ++ } ++ if (!thisHost.size()){ ++ thisHost = nullAddress; ++ } ++ sessions.setHost(thisHost); ++ } ++ ++ { ++ // Set active stream name to last active or "" if there were multiple streams active recently ++ std::string thisStream = ""; ++ for (std::map<std::string, uint64_t>::iterator it = streamLastActive.begin(); ++ it != streamLastActive.end(); ++it){ ++ if (now - it->second < STATS_DELAY){ ++ if (!thisStream.size()){ ++ thisStream = it->first; ++ }else if (thisStream != it->first){ ++ thisStream = ""; ++ break; ++ } ++ } ++ } ++ sessions.setStream(thisStream); ++ } ++ } ++ + // Retrigger USER_NEW if a re-sync was requested + if (!thisType && forceTrigger){ + forceTrigger = false; ++ std::string host; ++ Socket::hostBytesToStr(thisHost.data(), 16, host); + if (Triggers::shouldTrigger("USER_NEW", thisStreamName)){ + INFO_MSG("Triggering USER_NEW for stream %s", thisStreamName.c_str()); +- std::string payload = thisStreamName + "\n" + thisHost + "\n" + +- thisSid + "\n" + thisProtocol + ++ std::string payload = thisStreamName + "\n" + host + "\n" + ++ thisToken + "\n" + thisProtocol + + "\n" + thisReqUrl + "\n" + thisSessionId; + if (!Triggers::doTrigger("USER_NEW", payload, thisStreamName)){ + INFO_MSG("USER_NEW rejected stream %s", thisStreamName.c_str()); ++ Util::logExitReason("Session rejected by USER_NEW"); + connections.setExit(); + connections.finishAll(); ++ break; + }else{ + INFO_MSG("USER_NEW accepted stream %s", thisStreamName.c_str()); + } + } + } + +- // Invalidate connections if the session is marked as invalid +- if(connections.getExit()){ +- connections.finishAll(); +- break; +- } + // Remember latest activity so we know when this session ends + if (currentConnections){ +- lastSeen = Util::bootSecs(); + } +- Util::sleep(1000); ++ Util::wait(1000); ++ } ++ if (Util::bootSecs() - lastSeen > STATS_DELAY){ ++ Util::logExitReason("Session inactive for %d seconds", STATS_DELAY); + } + + // Trigger USER_END + if (!thisType && Triggers::shouldTrigger("USER_END", thisStreamName)){ +- lastSecond = 0; +- time = 0; +- down = 0; +- up = 0; +- +- // Get a final summary of this session +- for (uint64_t idx = 0; idx < connections.recordCount(); idx++){ +- if (connections.getStatus(idx) == COMM_STATUS_INVALID || connections.getStatus(idx) & COMM_STATUS_DISCONNECT){continue;} +- uint64_t thisLastSecond = connections.getLastSecond(idx); +- // Set last second to the latest entry +- if (thisLastSecond > lastSecond){ +- lastSecond = thisLastSecond; +- } +- // Count protocol durations across the entire session +- std::string thisConnector = connections.getConnector(idx); +- if (thisConnector != ""){ +- connectorCount[thisConnector] += connections.getTime(idx); +- } +- // Sum all other variables +- time += connections.getTime(idx); +- down += connections.getDown(idx); +- up += connections.getUp(idx); +- } + +- // Convert connector duration to string ++ // Convert connector, host and stream into lists and counts + std::stringstream connectorSummary; +- bool addDelimiter = false; +- connectorSummary << "{"; +- for (std::map<std::string, uint64_t>::iterator it = connectorCount.begin(); +- it != connectorCount.end(); ++it){ +- connectorSummary << (addDelimiter ? "," : "") << it->first << ":" << it->second; +- addDelimiter = true; ++ std::stringstream connectorTimes; ++ for (std::map<std::string, uint64_t>::iterator it = connectorCount.begin(); it != connectorCount.end(); ++it){ ++ connectorSummary << (connectorSummary.str().size() ? "," : "") << it->first; ++ connectorTimes << (connectorTimes.str().size() ? "," : "") << it->second; ++ } ++ std::stringstream hostSummary; ++ std::stringstream hostTimes; ++ for (std::map<std::string, uint64_t>::iterator it = hostCount.begin(); it != hostCount.end(); ++it){ ++ std::string host; ++ Socket::hostBytesToStr(it->first.data(), 16, host); ++ hostSummary << (hostSummary.str().size() ? "," : "") << host; ++ hostTimes << (hostTimes.str().size() ? "," : "") << it->second; ++ } ++ std::stringstream streamSummary; ++ std::stringstream streamTimes; ++ for (std::map<std::string, uint64_t>::iterator it = streamCount.begin(); it != streamCount.end(); ++it){ ++ streamSummary << (streamSummary.str().size() ? "," : "") << it->first; ++ streamTimes << (streamTimes.str().size() ? "," : "") << it->second; + } +- connectorSummary << "}"; + +- const uint64_t duration = lastSecond - (bootTime / 1000); + std::stringstream summary; +- summary << thisSessionId << "\n" +- << thisStreamName << "\n" ++ summary << thisToken << "\n" ++ << streamSummary.str() << "\n" + << connectorSummary.str() << "\n" +- << thisHost << "\n" +- << duration << "\n" +- << up << "\n" +- << down << "\n" +- << sessions.getTags(); ++ << hostSummary.str() << "\n" ++ << globalTime << "\n" ++ << globalUp << "\n" ++ << globalDown << "\n" ++ << sessions.getTags() << "\n" ++ << hostTimes.str() << "\n" ++ << connectorTimes.str() << "\n" ++ << streamTimes.str() << "\n" ++ << thisSessionId; + Triggers::doTrigger("USER_END", summary.str(), thisStreamName); + } + + if (!thisType && connections.getExit()){ +- WARN_MSG("Session %s has been invalidated since it is not allowed to view stream %s", thisSessionId.c_str(), thisStreamName.c_str()); + uint64_t sleepStart = Util::bootSecs(); + // Keep session invalidated for 10 minutes, or until the session stops +- while (config.is_active && sleepStart - Util::bootSecs() < 600){ ++ while (config.is_active && Util::bootSecs() - sleepStart < SESS_TIMEOUT){ + Util::sleep(1000); ++ if (forceTrigger){break;} + } + } +- INFO_MSG("Shutting down session %s", thisSessionId.c_str()); ++ INFO_MSG("Shutting down session %s: %s", thisSessionId.c_str(), Util::exitReason); + return 0; + } +-- +2.25.1 + + +From 1a4a526a112d0bdeaa0f269a133fe55c39a0d129 Mon Sep 17 00:00:00 2001 +From: Cat <carinasadres@gmail.com> +Date: Wed, 5 Oct 2022 03:10:04 +0200 +Subject: [PATCH 28/38] LSP: Moved some settings to new "General" tab, added + bitmask inputtype, removed LTSonly code + +--- + lsp/main.css | 30 +++ + lsp/minified.js | 396 ++++++++++++++++---------------- + lsp/mist.js | 582 +++++++++++++++++++++++++++++------------------- + 3 files changed, 590 insertions(+), 418 deletions(-) + +diff --git a/lsp/main.css b/lsp/main.css +index 6c72e6a7..9289d211 100644 +--- a/lsp/main.css ++++ b/lsp/main.css +@@ -279,6 +279,21 @@ main > button { + width: 1.5em; + flex-grow: 0; + } ++.input_container .field_container .field.bitmask { ++ display: flex; ++ flex-flow: row wrap; ++ justify-content: space-between; ++ padding: 0; ++ margin-bottom: 0.5em; ++} ++.input_container .field_container .field.bitmask > label { ++ display: flex; ++ flex-flow: row nowrap; ++ align-items: center; ++ margin-right: -0.25em; ++} ++.input_container .field_container .field.bitmask > label > input { margin: 0; } ++.input_container .field_container .field.bitmask > label > span { margin: 0 0.25em; } + textarea { + font-size: 0.8em; + } +@@ -349,6 +364,20 @@ select option[value=""] { + display: block; + z-index: 0; + } ++.input_container label.active { position: relative; } ++.input_container label.active:after { ++ content: ""; ++ display: block; ++ position: absolute; ++ z-index: -1; ++ top: -0.25em; ++ left: -0.25em; ++ width: 55.5em; ++ bottom: -0.25em; ++ background: linear-gradient(to right,#9ec2da,transparent 55em); ++ opacity: 0.3; ++ filter: blur(0.1em); ++} + .input_container label.active .ih_balloon, + .input_container > .help_container .ih_balloon { + display: block; +@@ -577,6 +606,7 @@ table.valigntop th { + } + .input_container .field_container .field.inputlist > * { + width: 100%; ++ box-sizing: border-box; + } + .input_container .field_container .field.checkcontainer { + font-size: 0.8em; +diff --git a/lsp/minified.js b/lsp/minified.js +index 52a6f6bc..9db52d63 100644 +--- a/lsp/minified.js ++++ b/lsp/minified.js +@@ -1,11 +1,11 @@ +-var MD5=function(a){function b(a,b){var c,d,g,i,e;g=a&2147483648;i=b&2147483648;c=a&1073741824;d=b&1073741824;e=(a&1073741823)+(b&1073741823);return c&d?e^2147483648^g^i:c|d?e&1073741824?e^3221225472^g^i:e^1073741824^g^i:e^g^i}function c(a,c,d,g,i,e,f){a=b(a,b(b(c&d|~c&g,i),f));return b(a<<e|a>>>32-e,c)}function d(a,c,d,g,i,e,f){a=b(a,b(b(c&g|d&~g,i),f));return b(a<<e|a>>>32-e,c)}function e(a,c,d,g,e,i,f){a=b(a,b(b(c^d^g,e),f));return b(a<<i|a>>>32-i,c)}function l(a,c,d,g,i,e,f){a=b(a,b(b(d^(c|~g), +-i),f));return b(a<<e|a>>>32-e,c)}function m(a){var b="",c="",d;for(d=0;3>=d;d++)c=a>>>8*d&255,c="0"+c.toString(16),b+=c.substr(c.length-2,2);return b}var f=[],t,o,k,w,h,g,i,j,f=a.replace(/\r\n/g,"\n"),a="";for(t=0;t<f.length;t++)o=f.charCodeAt(t),128>o?a+=String.fromCharCode(o):(127<o&&2048>o?a+=String.fromCharCode(o>>6|192):(a+=String.fromCharCode(o>>12|224),a+=String.fromCharCode(o>>6&63|128)),a+=String.fromCharCode(o&63|128));f=a;a=f.length;t=a+8;o=16*((t-t%64)/64+1);k=Array(o-1);for(h=w=0;h<a;)t= +-(h-h%4)/4,w=8*(h%4),k[t]|=f.charCodeAt(h)<<w,h++;t=(h-h%4)/4;k[t]|=128<<8*(h%4);k[o-2]=a<<3;k[o-1]=a>>>29;f=k;h=1732584193;g=4023233417;i=2562383102;j=271733878;for(a=0;a<f.length;a+=16)t=h,o=g,k=i,w=j,h=c(h,g,i,j,f[a+0],7,3614090360),j=c(j,h,g,i,f[a+1],12,3905402710),i=c(i,j,h,g,f[a+2],17,606105819),g=c(g,i,j,h,f[a+3],22,3250441966),h=c(h,g,i,j,f[a+4],7,4118548399),j=c(j,h,g,i,f[a+5],12,1200080426),i=c(i,j,h,g,f[a+6],17,2821735955),g=c(g,i,j,h,f[a+7],22,4249261313),h=c(h,g,i,j,f[a+8],7,1770035416), +-j=c(j,h,g,i,f[a+9],12,2336552879),i=c(i,j,h,g,f[a+10],17,4294925233),g=c(g,i,j,h,f[a+11],22,2304563134),h=c(h,g,i,j,f[a+12],7,1804603682),j=c(j,h,g,i,f[a+13],12,4254626195),i=c(i,j,h,g,f[a+14],17,2792965006),g=c(g,i,j,h,f[a+15],22,1236535329),h=d(h,g,i,j,f[a+1],5,4129170786),j=d(j,h,g,i,f[a+6],9,3225465664),i=d(i,j,h,g,f[a+11],14,643717713),g=d(g,i,j,h,f[a+0],20,3921069994),h=d(h,g,i,j,f[a+5],5,3593408605),j=d(j,h,g,i,f[a+10],9,38016083),i=d(i,j,h,g,f[a+15],14,3634488961),g=d(g,i,j,h,f[a+4],20,3889429448), +-h=d(h,g,i,j,f[a+9],5,568446438),j=d(j,h,g,i,f[a+14],9,3275163606),i=d(i,j,h,g,f[a+3],14,4107603335),g=d(g,i,j,h,f[a+8],20,1163531501),h=d(h,g,i,j,f[a+13],5,2850285829),j=d(j,h,g,i,f[a+2],9,4243563512),i=d(i,j,h,g,f[a+7],14,1735328473),g=d(g,i,j,h,f[a+12],20,2368359562),h=e(h,g,i,j,f[a+5],4,4294588738),j=e(j,h,g,i,f[a+8],11,2272392833),i=e(i,j,h,g,f[a+11],16,1839030562),g=e(g,i,j,h,f[a+14],23,4259657740),h=e(h,g,i,j,f[a+1],4,2763975236),j=e(j,h,g,i,f[a+4],11,1272893353),i=e(i,j,h,g,f[a+7],16,4139469664), +-g=e(g,i,j,h,f[a+10],23,3200236656),h=e(h,g,i,j,f[a+13],4,681279174),j=e(j,h,g,i,f[a+0],11,3936430074),i=e(i,j,h,g,f[a+3],16,3572445317),g=e(g,i,j,h,f[a+6],23,76029189),h=e(h,g,i,j,f[a+9],4,3654602809),j=e(j,h,g,i,f[a+12],11,3873151461),i=e(i,j,h,g,f[a+15],16,530742520),g=e(g,i,j,h,f[a+2],23,3299628645),h=l(h,g,i,j,f[a+0],6,4096336452),j=l(j,h,g,i,f[a+7],10,1126891415),i=l(i,j,h,g,f[a+14],15,2878612391),g=l(g,i,j,h,f[a+5],21,4237533241),h=l(h,g,i,j,f[a+12],6,1700485571),j=l(j,h,g,i,f[a+3],10,2399980690), +-i=l(i,j,h,g,f[a+10],15,4293915773),g=l(g,i,j,h,f[a+1],21,2240044497),h=l(h,g,i,j,f[a+8],6,1873313359),j=l(j,h,g,i,f[a+15],10,4264355552),i=l(i,j,h,g,f[a+6],15,2734768916),g=l(g,i,j,h,f[a+13],21,1309151649),h=l(h,g,i,j,f[a+4],6,4149444226),j=l(j,h,g,i,f[a+11],10,3174756917),i=l(i,j,h,g,f[a+2],15,718787259),g=l(g,i,j,h,f[a+9],21,3951481745),h=b(h,t),g=b(g,o),i=b(i,k),j=b(j,w);return(m(h)+m(g)+m(i)+m(j)).toLowerCase()};(function(a){a.fn.stupidtable=function(){a(this).on("click","thead th",function(){a(this).stupidsort()})};a.fn.stupidsort=function(){function b(b){var c=0,d;a(b).children("td,th").each(function(){if(c==t)return d=a(this),!1;var b=a(this).attr("colspan");c+=b?Number(b):1});b="undefined"!=typeof d.data("sort-value")?d.data("sort-value"):"undefined"!=typeof d.attr("data-sort-value")?d.attr("data-sort-value"):d.text();switch(m){case "string":case "string-ins":b=String(b).toLowerCase();break;case "int":b= +-parseInt(Number(b));break;case "float":b=Number(b)}return b}var c=a(this),d=c.closest("table"),e=d.children("tbody"),l=e.children("tr"),m=c.attr("data-sort-type");if(m){var f=!0;c.hasClass("sorting-asc")&&(f=!1);var t=0;c.prevAll().each(function(){var b=a(this).attr("colspan");t+=b?Number(b):1});l.sort(function(a,c){var d=f?1:-1,a=b(a),c=b(c);return a>c?1*d:a<c?-1*d:0});e.append(l);d.find("thead th").removeClass("sorting-asc").removeClass("sorting-desc");c.addClass(f?"sorting-asc":"sorting-desc")}}})(jQuery);$(function(){UI.elements={menu:$("nav > .menu"),main:$("main"),header:$("header"),connection:{status:$("#connection"),user_and_host:$("#user_and_host"),msg:$("#message")}};UI.buildMenu();UI.stored.getOpts();try{if("mistLogin"in sessionStorage){var a=JSON.parse(sessionStorage.mistLogin);mist.user.name=a.name;mist.user.password=a.password;mist.user.host=a.host}}catch(b){}location.hash&&(a=decodeURIComponent(location.hash).substring(1).split("@")[0].split("&"),mist.user.name=a[0],a[1]&&(mist.user.host= ++var MD5=function(a){function b(a,b){var c,d,g,f,e;g=a&2147483648;f=b&2147483648;c=a&1073741824;d=b&1073741824;e=(a&1073741823)+(b&1073741823);return c&d?e^2147483648^g^f:c|d?e&1073741824?e^3221225472^g^f:e^1073741824^g^f:e^g^f}function c(a,c,d,g,f,e,h){a=b(a,b(b(c&d|~c&g,f),h));return b(a<<e|a>>>32-e,c)}function d(a,c,d,g,e,f,h){a=b(a,b(b(c&g|d&~g,e),h));return b(a<<f|a>>>32-f,c)}function e(a,c,d,g,f,e,h){a=b(a,b(b(c^d^g,f),h));return b(a<<e|a>>>32-e,c)}function l(a,c,d,g,e,f,h){a=b(a,b(b(d^(c|~g), ++e),h));return b(a<<f|a>>>32-f,c)}function n(a){var b="",c="",d;for(d=0;3>=d;d++)c=a>>>8*d&255,c="0"+c.toString(16),b+=c.substr(c.length-2,2);return b}var h=[],t,m,k,w,i,g,f,j,h=a.replace(/\r\n/g,"\n"),a="";for(t=0;t<h.length;t++)m=h.charCodeAt(t),128>m?a+=String.fromCharCode(m):(127<m&&2048>m?a+=String.fromCharCode(m>>6|192):(a+=String.fromCharCode(m>>12|224),a+=String.fromCharCode(m>>6&63|128)),a+=String.fromCharCode(m&63|128));h=a;a=h.length;t=a+8;m=16*((t-t%64)/64+1);k=Array(m-1);for(i=w=0;i<a;)t= ++(i-i%4)/4,w=8*(i%4),k[t]|=h.charCodeAt(i)<<w,i++;t=(i-i%4)/4;k[t]|=128<<8*(i%4);k[m-2]=a<<3;k[m-1]=a>>>29;h=k;i=1732584193;g=4023233417;f=2562383102;j=271733878;for(a=0;a<h.length;a+=16)t=i,m=g,k=f,w=j,i=c(i,g,f,j,h[a+0],7,3614090360),j=c(j,i,g,f,h[a+1],12,3905402710),f=c(f,j,i,g,h[a+2],17,606105819),g=c(g,f,j,i,h[a+3],22,3250441966),i=c(i,g,f,j,h[a+4],7,4118548399),j=c(j,i,g,f,h[a+5],12,1200080426),f=c(f,j,i,g,h[a+6],17,2821735955),g=c(g,f,j,i,h[a+7],22,4249261313),i=c(i,g,f,j,h[a+8],7,1770035416), ++j=c(j,i,g,f,h[a+9],12,2336552879),f=c(f,j,i,g,h[a+10],17,4294925233),g=c(g,f,j,i,h[a+11],22,2304563134),i=c(i,g,f,j,h[a+12],7,1804603682),j=c(j,i,g,f,h[a+13],12,4254626195),f=c(f,j,i,g,h[a+14],17,2792965006),g=c(g,f,j,i,h[a+15],22,1236535329),i=d(i,g,f,j,h[a+1],5,4129170786),j=d(j,i,g,f,h[a+6],9,3225465664),f=d(f,j,i,g,h[a+11],14,643717713),g=d(g,f,j,i,h[a+0],20,3921069994),i=d(i,g,f,j,h[a+5],5,3593408605),j=d(j,i,g,f,h[a+10],9,38016083),f=d(f,j,i,g,h[a+15],14,3634488961),g=d(g,f,j,i,h[a+4],20,3889429448), ++i=d(i,g,f,j,h[a+9],5,568446438),j=d(j,i,g,f,h[a+14],9,3275163606),f=d(f,j,i,g,h[a+3],14,4107603335),g=d(g,f,j,i,h[a+8],20,1163531501),i=d(i,g,f,j,h[a+13],5,2850285829),j=d(j,i,g,f,h[a+2],9,4243563512),f=d(f,j,i,g,h[a+7],14,1735328473),g=d(g,f,j,i,h[a+12],20,2368359562),i=e(i,g,f,j,h[a+5],4,4294588738),j=e(j,i,g,f,h[a+8],11,2272392833),f=e(f,j,i,g,h[a+11],16,1839030562),g=e(g,f,j,i,h[a+14],23,4259657740),i=e(i,g,f,j,h[a+1],4,2763975236),j=e(j,i,g,f,h[a+4],11,1272893353),f=e(f,j,i,g,h[a+7],16,4139469664), ++g=e(g,f,j,i,h[a+10],23,3200236656),i=e(i,g,f,j,h[a+13],4,681279174),j=e(j,i,g,f,h[a+0],11,3936430074),f=e(f,j,i,g,h[a+3],16,3572445317),g=e(g,f,j,i,h[a+6],23,76029189),i=e(i,g,f,j,h[a+9],4,3654602809),j=e(j,i,g,f,h[a+12],11,3873151461),f=e(f,j,i,g,h[a+15],16,530742520),g=e(g,f,j,i,h[a+2],23,3299628645),i=l(i,g,f,j,h[a+0],6,4096336452),j=l(j,i,g,f,h[a+7],10,1126891415),f=l(f,j,i,g,h[a+14],15,2878612391),g=l(g,f,j,i,h[a+5],21,4237533241),i=l(i,g,f,j,h[a+12],6,1700485571),j=l(j,i,g,f,h[a+3],10,2399980690), ++f=l(f,j,i,g,h[a+10],15,4293915773),g=l(g,f,j,i,h[a+1],21,2240044497),i=l(i,g,f,j,h[a+8],6,1873313359),j=l(j,i,g,f,h[a+15],10,4264355552),f=l(f,j,i,g,h[a+6],15,2734768916),g=l(g,f,j,i,h[a+13],21,1309151649),i=l(i,g,f,j,h[a+4],6,4149444226),j=l(j,i,g,f,h[a+11],10,3174756917),f=l(f,j,i,g,h[a+2],15,718787259),g=l(g,f,j,i,h[a+9],21,3951481745),i=b(i,t),g=b(g,m),f=b(f,k),j=b(j,w);return(n(i)+n(g)+n(f)+n(j)).toLowerCase()};(function(a){a.fn.stupidtable=function(){a(this).on("click","thead th",function(){a(this).stupidsort()})};a.fn.stupidsort=function(){function b(b){var c=0,d;a(b).children("td,th").each(function(){if(c==t)return d=a(this),!1;var b=a(this).attr("colspan");c+=b?Number(b):1});b="undefined"!=typeof d.data("sort-value")?d.data("sort-value"):"undefined"!=typeof d.attr("data-sort-value")?d.attr("data-sort-value"):d.text();switch(n){case "string":case "string-ins":b=String(b).toLowerCase();break;case "int":b= ++parseInt(Number(b));break;case "float":b=Number(b)}return b}var c=a(this),d=c.closest("table"),e=d.children("tbody"),l=e.children("tr"),n=c.attr("data-sort-type");if(n){var h=!0;c.hasClass("sorting-asc")&&(h=!1);var t=0;c.prevAll().each(function(){var b=a(this).attr("colspan");t+=b?Number(b):1});l.sort(function(a,c){var d=h?1:-1,a=b(a),c=b(c);return a>c?1*d:a<c?-1*d:0});e.append(l);d.find("thead th").removeClass("sorting-asc").removeClass("sorting-desc");c.addClass(h?"sorting-asc":"sorting-desc")}}})(jQuery);$(function(){UI.elements={menu:$("nav > .menu"),main:$("main"),header:$("header"),connection:{status:$("#connection"),user_and_host:$("#user_and_host"),msg:$("#message")}};UI.buildMenu();UI.stored.getOpts();try{if("mistLogin"in sessionStorage){var a=JSON.parse(sessionStorage.mistLogin);mist.user.name=a.name;mist.user.password=a.password;mist.user.host=a.host}}catch(b){}location.hash&&(a=decodeURIComponent(location.hash).substring(1).split("@")[0].split("&"),mist.user.name=a[0],a[1]&&(mist.user.host= + a[1]));mist.send(function(){$(window).trigger("hashchange")},{},{timeout:5,hide:!0});var c=0;$("body > div.filler").on("scroll",function(){var a=$(this).scrollLeft();a!=c&&UI.elements.header.css("margin-right",-1*a+"px");c=a})});$(window).on("hashchange",function(){var a=decodeURIComponent(location.hash).substring(1).split("@");a[1]||(a[1]="");a=a[1].split("&");""==a[0]&&(a[0]="Overview");UI.showTab(a[0],a[1])}); + var MistVideoObject={},otherhost={host:!1,https:!1},UI={debug:!1,elements:{},stored:{getOpts:function(){var a=localStorage.stored;a&&(a=JSON.parse(a));$.extend(!0,this.vars,a);return this.vars},saveOpt:function(a,b){this.vars[a]=b;localStorage.stored=JSON.stringify(this.vars);return this.vars},vars:{helpme:!0}},interval:{clear:function(){"undefined"!=typeof this.opts&&(clearInterval(this.opts.id),delete this.opts)},set:function(a,b){this.opts&&log("[interval]","Set called on interval, but an interval is already active."); + this.opts={delay:b,callback:a};this.opts.id=setInterval(a,b)}},returnTab:["Overview"],countrylist:{AF:"Afghanistan",AX:"Åland Islands",AL:"Albania",DZ:"Algeria",AS:"American Samoa",AD:"Andorra",AO:"Angola",AI:"Anguilla",AQ:"Antarctica",AG:"Antigua and Barbuda",AR:"Argentina",AM:"Armenia",AW:"Aruba",AU:"Australia",AT:"Austria",AZ:"Azerbaijan",BS:"Bahamas",BH:"Bahrain",BD:"Bangladesh",BB:"Barbados",BY:"Belarus",BE:"Belgium",BZ:"Belize",BJ:"Benin",BM:"Bermuda",BT:"Bhutan",BO:"Bolivia, Plurinational State of", +@@ -20,61 +20,61 @@ TV:"Tuvalu",UG:"Uganda",UA:"Ukraine",AE:"United Arab Emirates",GB:"United Kingdo + clearTimeout(this.hiding);delete this.hiding;var c=$(document).height()-$tooltip.outerHeight(),d=$(document).width()-$tooltip.outerWidth();$tooltip.css("left",Math.min(a.pageX+10,d-10));$tooltip.css("top",Math.min(a.pageY+25,c-10));$tooltip.show().addClass("show")},hide:function(){$tooltip=this.element;$tooltip.removeClass("show");this.hiding=setTimeout(function(){$tooltip.hide()},500)},element:$("<div>").attr("id","tooltip")},humanMime:function(a){var b=!1;switch(a){case "html5/application/vnd.apple.mpegurl":b= + "HLS (TS)";break;case "html5/application/vnd.apple.mpegurl;version=7":b="HLS (CMAF)";break;case "html5/video/webm":b="WebM";break;case "html5/video/mp4":b="MP4";break;case "dash/video/mp4":b="DASH";break;case "flash/11":b="HDS";break;case "flash/10":b="RTMP";break;case "flash/7":b="Progressive";break;case "html5/audio/mp3":b="MP3";break;case "html5/audio/wav":b="WAV";break;case "html5/video/mp2t":case "html5/video/mpeg":b="TS";break;case "html5/application/vnd.ms-sstr+xml":case "html5/application/vnd.ms-ss":b= + "Smooth Streaming";break;case "html5/text/vtt":b="VTT Subtitles";break;case "html5/text/plain":b="SRT Subtitles";break;case "html5/text/javascript":b="JSON Subtitles";break;case "rtsp":b="RTSP";break;case "webrtc":b="WebRTC"}return b},popup:{element:null,show:function(a){this.element=$("<div>").attr("id","popup").append($("<button>").text("Close").addClass("close").click(function(){UI.popup.element.fadeOut("fast",function(){UI.popup.element.remove();UI.popup.element=null})})).append(a);$("body").append(this.element)}}, +-menu:[{Overview:{},Protocols:{},Streams:{hiddenmenu:{Edit:{},Preview:{},Embed:{}}},Push:{LTSonly:!0},Triggers:{LTSonly:!1},Logs:{},Statistics:{},"Server Stats":{}},{Disconnect:{classes:["red"]}},{Guides:{link:"http://mistserver.org/documentation#Userdocs"},Tools:{submenu:{"Release notes":{link:"http://mistserver.org/documentation#Devdocs"},"Mist Shop":{link:"http://mistserver.org/products"},"Email for Help":{}}}}],buildMenu:function(){function a(a,b){var c=$("<a>").addClass("button");c.html($("<span>").addClass("plain").text(a)).append($("<span>").addClass("highlighted").text(a)); +-for(var d in b.classes)c.addClass(b.classes[d]);"LTSonly"in b&&c.addClass("LTSonly");"link"in b?c.attr("href",b.link).attr("target","_blank"):"submenu"in b||c.click(function(b){$(this).closest(".menu").hasClass("hide")||(UI.navto(a),b.stopPropagation())});return c}var b=UI.elements.menu,c;for(c in UI.menu){0<c&&b.append($("<br>"));for(var d in UI.menu[c]){var e=UI.menu[c][d],l=a(d,e);b.append(l);if("submenu"in e){var m=$("<span>").addClass("submenu");l.addClass("arrowdown").append(m);for(var f in e.submenu)m.append(a(f, +-e.submenu[f]))}else if("hiddenmenu"in e)for(f in m=$("<span>").addClass("hiddenmenu"),l.append(m),e.hiddenmenu)m.append(a(f,e.hiddenmenu[f]))}}c=$("<div>").attr("id","ih_button").text("?").click(function(){$("body").toggleClass("helpme");UI.stored.saveOpt("helpme",$("body").hasClass("helpme"))}).attr("title","Click to toggle the display of integrated help");UI.stored.getOpts().helpme&&$("body").addClass("helpme");b.after(c).after($("<div>").addClass("separator"))},findInput:function(a){return this.findInOutput("inputs", +-a)},findOutput:function(a){return this.findInOutput("connectors",a)},findInOutput:function(a,b){if("capabilities"in mist.data){var c=!1,d=mist.data.capabilities[a];b in d&&(c=d[b]);b+".exe"in d&&(c=d[b+".exe"]);return c}throw"Request capabilities first";},buildUI:function(a){var b=$("<div>").addClass("input_container"),c;for(c in a){var d=a[c];if(d instanceof jQuery)b.append(d);else if("help"==d.type){var e=$("<span>").addClass("text_container").append($("<span>").addClass("description").append(d.help)); +-b.append(e);if("classes"in d)for(var l in d.classes)e.addClass(d.classes[l])}else if("text"==d.type)b.append($("<span>").addClass("text_container").append($("<span>").addClass("text").append(d.text)));else if("custom"==d.type)b.append(d.custom);else if("buttons"==d.type)for(l in e=$("<span>").addClass("button_container").on("keydown",function(a){a.stopPropagation()}),"css"in d&&e.css(d.css),b.append(e),d.buttons){var m=d.buttons[l],f=$("<button>").text(m.label).data("opts",m);"css"in m&&f.css(m.css); +-if("classes"in m)for(var t in m.classes)f.addClass(m.classes[t]);e.append(f);switch(m.type){case "cancel":f.addClass("cancel").click(m["function"]);break;case "save":f.addClass("save").click(function(){var a=$(this).data("opts").preSave;a&&a.call(this);var b=$(this).closest(".input_container"),c=!1;b.find('.hasValidate:visible, input[type="hidden"].hasValidate').each(function(){if(c=$(this).data("validate")(this,!0))return!1});(a=$(this).data("opts").failedValidate)&&a.call(this);c||(b.find('.isSetting:visible, input[type="hidden"].isSetting').each(function(){var a= +-$(this).getval(),b=$(this).data("pointer");if(""===a)if("default"in $(this).data("opts"))a=$(this).data("opts")["default"];else return b.main[b.index]=null,!0;b.main[b.index]=a}),(a=$(this).data("opts")["function"])&&a(this))});break;default:f.click(m["function"])}}else{m=$("<label>").addClass("UIelement");b.append(m);"css"in d&&m.css(d.css);m.append($("<span>").addClass("label").html("label"in d?d.label+":":""));if("classes"in d)for(t in d.classes)m.addClass(d.classes[t]);f=$("<span>").addClass("field_container"); +-m.append(f);switch(d.type){case "password":e=$("<input>").attr("type","password");break;case "int":e=$("<input>").attr("type","number");"min"in d&&e.attr("min",d.min);"max"in d&&e.attr("max",d.max);"step"in d&&e.attr("step",d.step);"validate"in d?d.validate.push("int"):d.validate=["int"];break;case "span":e=$("<span>");break;case "debug":d.select=[["","Default"],[0,"0 - All debugging messages disabled"],[1,"1 - Messages about failed operations"],[2,"2 - Previous level, and error messages"],[3,"3 - Previous level, and warning messages"], +-[4,"4 - Previous level, and status messages for development"],[5,"5 - Previous level, and more status messages for development"],[6,"6 - Previous level, and verbose debugging messages"],[7,"7 - Previous level, and very verbose debugging messages"],[8,"8 - Report everything in extreme detail"],[9,"9 - Report everything in insane detail"],[10,"10 - All messages enabled"]];case "select":e=$("<select>");for(l in d.select){var o=$("<option>");"string"==typeof d.select[l]?o.text(d.select[l]):o.val(d.select[l][0]).text(d.select[l][1]); +-e.append(o)}break;case "textarea":e=$("<textarea>").on("keydown",function(a){a.stopPropagation()});break;case "checkbox":e=$("<input>").attr("type","checkbox");break;case "hidden":e=$("<input>").attr("type","hidden");m.hide();break;case "email":e=$("<input>").attr("type","email").attr("autocomplete","on").attr("required","");break;case "browse":e=$("<input>").attr("type","text");"filetypes"in d&&e.data("filetypes",d.filetypes);break;case "geolimited":case "hostlimited":e=$("<input>").attr("type", +-"hidden");break;case "radioselect":e=$("<div>").addClass("radioselect");for(c in d.radioselect){var k=$("<input>").attr("type","radio").val(d.radioselect[c][0]).attr("name",d.label);("LTSonly"in d&&!mist.data.LTS||d.readonly)&&k.prop("disabled",!0);o=$("<label>").append(k).append($("<span>").html(d.radioselect[c][1]));e.append(o);if(2<d.radioselect[c].length)for(l in k=$("<select>").change(function(){$(this).parent().find("input[type=radio]:enabled").prop("checked","true")}),o.append(k),("LTSonly"in +-d&&!mist.data.LTS||d.readonly)&&k.prop("disabled",!0),d.radioselect[c][2])o=$("<option>"),k.append(o),d.radioselect[c][2][l]instanceof Array?o.val(d.radioselect[c][2][l][0]).html(d.radioselect[c][2][l][1]):o.html(d.radioselect[c][2][l])}break;case "checklist":e=$("<div>").addClass("checkcontainer");$controls=$("<div>").addClass("controls");$checklist=$("<div>").addClass("checklist");e.append($checklist);for(c in d.checklist)"string"==typeof d.checklist[c]&&(d.checklist[c]=[d.checklist[c],d.checklist[c]]), +-$checklist.append($("<label>").text(d.checklist[c][1]).prepend($("<input>").attr("type","checkbox").attr("name",d.checklist[c][0])));break;case "DOMfield":e=d.DOMfield;break;case "unix":e=$("<input>").attr("type","datetime-local").attr("step",1);d.unit=$("<button>").text("Now").click(function(){$(this).closest(".field_container").find(".field").setval((new Date).getTime()/1E3)});break;case "selectinput":e=$("<div>").addClass("selectinput");k=$("<select>");e.append(k);k.data("input",!1);"LTSonly"in +-d&&!mist.data.LTS&&k.prop("disabled",!0);for(c in d.selectinput)o=$("<option>"),k.append(o),"string"==typeof d.selectinput[c]?o.text(d.selectinput[c]):(o.text(d.selectinput[c][1]),"string"==typeof d.selectinput[c][0]?o.val(d.selectinput[c][0]):(o.val("CUSTOM"),k.data("input")||k.data("input",UI.buildUI([d.selectinput[c][0]]).children())));k.data("input")&&e.append(k.data("input"));k.change(function(){"CUSTOM"==$(this).val()?$(this).data("input").css("display","flex"):$(this).data("input").hide()}); +-k.trigger("change");break;case "inputlist":e=$("<div>").addClass("inputlist");e.data("newitem",function(){var a=$("<input>").attr("type","text").addClass("listitem");("LTSonly"in d&&!mist.data.LTS||d.readonly)&&a.prop("disabled",!0);var b=function(c){$(this).is(":last-child")?""!=$(this).val()?$(this).after(a.clone().keyup(b).val("")):8==c.which&&$(this).prev().focus():""==$(this).val()&&($(this).next().focus(),$(this).remove())};a.keyup(b);return a});e.append(e.data("newitem"));break;case "sublist":e= +-$("<div>").addClass("sublist");k=$("<div>").addClass("curvals");k.append($("<span>").text("None."));var w=$("<div>").addClass("itemsettings"),h=$("<button>").text("New "+d.itemLabel),g=d.sublist,i=d,j=e,Q=m;e.data("build",function(a,b){for(var c in i.saveas)c in a||delete i.saveas[c];i.saveas=Object.assign(i.saveas,a);c="New";"undefined"!=typeof b&&(c="Edit");c=UI.buildUI([$("<h4>").text(c+" "+i.itemLabel)].concat(g).concat([{label:"Save first",type:"str",classes:["onlyshowhelp"],validate:[function(){return{msg:"Did you want to save this "+ +-i.itemLabel+"?",classes:["red"]}}]},{type:"buttons",buttons:[{label:"Cancel",type:"cancel","function":function(){w.html("");h.show();Q.show()}},{label:"Save "+i.itemLabel,type:"save",preSave:function(){$(this).closest(".input_container").find(".onlyshowhelp").closest("label").hide()},failedValidate:function(){$(this).closest(".input_container").find(".onlyshowhelp").closest("label").show()},"function":function(){var a=j.getval(),c=Object.assign({},i.saveas),d;for(d in c)null===c[d]&&delete c[d];"undefined"== +-typeof b?a.push(c):a[b]=c;j.setval(a);w.html("");h.show();Q.show()}}]}]));w.html(c);h.hide();Q.hide()});var F=e;h.click(function(){F.data("build")({})});g.unshift({type:"str",label:"Human readable name",placeholder:"none",help:"A convenient name to describe this "+d.itemLabel+". It won't be used by MistServer.",pointer:{main:d.saveas,index:"x-LSP-name"}});e.data("savelist",[]);e.append(k).append(h);b.append(w);break;case "json":e=$("<textarea>").on("keydown",function(a){a.stopPropagation()}).on("keyup change", +-function(){this.style.height="";this.style.height=(this.scrollHeight?this.scrollHeight+20:14*this.value.split("\n").length+20)+"px"}).css("min-height","3em");k=function(a,b){if(""!=$(b).val()&&null===a)return{msg:"Invalid json",classes:["red"]}};"validate"in d?d.validate.push(k):d.validate=[k];break;default:e=$("<input>").attr("type","text")}e.addClass("field").data("opts",d);"pointer"in d&&e.attr("name",d.pointer.index);f.append(e);if("classes"in d)for(l in d.classes)e.addClass(d.classes[l]);"placeholder"in +-d&&e.attr("placeholder",d.placeholder);"default"in d&&e.attr("placeholder",d["default"]);"unit"in d&&f.append($("<span>").addClass("unit").html(d.unit));"readonly"in d&&(e.attr("readonly","readonly"),e.click(function(){$(this).select()}));"qrcode"in d&&f.append($("<span>").addClass("unit").html($("<button>").text("QR").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=String($(this).closest(".field_container").find(".field").getval()),b=$("<div>").addClass("qrcode");UI.popup.show($("<span>").addClass("qr_container").append($("<p>").text(a)).append(b)); +-b.qrcode({text:a,size:Math.min(b.width(),b.height())})})));"clipboard"in d&&document.queryCommandSupported("copy")&&f.append($("<span>").addClass("unit").html($("<button>").text("Copy").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=String($(this).closest(".field_container").find(".field").getval()),b=document.createElement("textarea");b.value=a;document.body.appendChild(b);b.select();var c=false;try{c=document.execCommand("copy")}catch(d){}if(c){$(this).text("Copied to clipboard!"); +-document.body.removeChild(b);var g=$(this);setTimeout(function(){g.text("Copy")},5E3)}else{document.body.removeChild(b);alert("Failed to copy:\n"+a)}})));"rows"in d&&e.attr("rows",d.rows);"LTSonly"in d&&!mist.data.LTS&&(f.addClass("LTSonly"),e.prop("disabled",!0));if("dependent"in d)for(c in d.dependent)m.attr("data-dependent-"+c,d.dependent[c]);switch(d.type){case "browse":k=$("<div>").addClass("grouper").append(m);b.append(k);k=$("<button>").text("Browse").on("keydown",function(a){a.stopPropagation()}); +-f.append(k);k.click(function(){function a(b){f.text("Loading..");mist.send(function(a){i.text(a.browse.path[0]);mist.data.LTS&&d.setval(a.browse.path[0]+"/");f.html(h.clone(true).text("..").attr("title","Folder up"));if(a.browse.subdirectories){a.browse.subdirectories.sort();for(var b in a.browse.subdirectories){var e=a.browse.subdirectories[b];f.append(h.clone(true).attr("title",i.text()+m+e).text(e))}}if(a.browse.files){a.browse.files.sort();for(b in a.browse.files){var e=a.browse.files[b],r=i.text()+ +-m+e,e=$("<a>").text(e).addClass("file").attr("title",r);f.append(e);if(j){var k=true,l;for(l in j)if(typeof j[l]!="undefined"&&mist.inputMatch(j[l],r)){k=false;break}k&&e.hide()}e.click(function(){var a=$(this).attr("title");d.setval(a).removeAttr("readonly").css("opacity",1);g.show();c.remove()})}}},{browse:b})}var b=$(this).closest(".grouper"),c=$("<div>").addClass("browse_container"),d=b.find(".field").attr("readonly","readonly").css("opacity",0.5),g=$(this),e=$("<button>").text("Stop browsing").click(function(){g.show(); +-c.remove();d.removeAttr("readonly").css("opacity",1)}),i=$("<span>").addClass("field"),f=$("<div>").addClass("browse_contents"),h=$("<a>").addClass("folder"),j=d.data("filetypes");b.append(c);c.append($("<label>").addClass("UIelement").append($("<span>").addClass("label").text("Current folder:")).append($("<span>").addClass("field_container").append(i).append(e))).append(f);var m="/";mist.data.config.version.indexOf("indows")>-1&&(m="\\");h.click(function(){var b=i.text()+m+$(this).text();a(b)}); +-b=d.getval();e=b.split("://");e.length>1&&(b=e[0]=="file"?e[1]:"");b=b.split(m);b.pop();b=b.join(m);g.hide();a(b)});break;case "geolimited":case "hostlimited":k={field:e};k.blackwhite=$("<select>").append($("<option>").val("-").text("Blacklist")).append($("<option>").val("+").text("Whitelist"));k.values=$("<span>").addClass("limit_value_list");switch(d.type){case "geolimited":k.prototype=$("<select>").append($("<option>").val("").text("[Select a country]"));for(c in UI.countrylist)k.prototype.append($("<option>").val(c).html(UI.countrylist[c])); +-break;case "hostlimited":k.prototype=$("<input>").attr("type","text").attr("placeholder","type a host")}k.prototype.on("change keyup",function(){$(this).closest(".field_container").data("subUI").blackwhite.trigger("change")});k.blackwhite.change(function(){var a=$(this).closest(".field_container").data("subUI"),b=[],c=false;a.values.children().each(function(){c=$(this).val();c!=""?b.push(c):$(this).remove()});a.values.append(a.prototype.clone(true));b.length>0?a.field.val($(this).val()+b.join(" ")): +-a.field.val("");a.field.trigger("change")});"LTSonly"in d&&!mist.data.LTS&&(k.blackwhite.prop("disabled",!0),k.prototype.prop("disabled",!0));k.values.append(k.prototype.clone(!0));f.data("subUI",k).addClass("limit_list").append(k.blackwhite).append(k.values)}"pointer"in d&&(e.data("pointer",d.pointer).addClass("isSetting"),d.pointer.main&&(k=d.pointer.main[d.pointer.index],"undefined"!=k&&e.setval(k)));(""==e.getval()||null==e.getval())&&"value"in d&&e.setval(d.value);if("datalist"in d)for(c in k= +-"datalist_"+c+MD5(e[0].outerHTML),e.attr("list",k),k=$("<datalist>").attr("id",k),f.append(k),d.datalist)k.append($("<option>").val(d.datalist[c]));f=$("<span>").addClass("help_container");m.append(f);"help"in d&&(f.append($("<span>").addClass("ih_balloon").html(d.help)),e.on("focus mouseover",function(){$(this).closest("label").addClass("active")}).on("blur mouseout",function(){$(this).closest("label").removeClass("active")}));if("validate"in d){m=[];for(l in d.validate){k=d.validate[l];if("function"!= +-typeof k)switch(k){case "required":k=function(a){return a==""||a==null?{msg:"This is a required field.",classes:["red"]}:false};break;case "int":k=function(a,b){var c=$(b).data("opts");if(!$(b)[0].validity.valid){var d=[];"min"in c&&d.push(" greater than or equal to "+c.min);"max"in c&&d.push(" smaller than or equal to "+c.max);return{msg:"Please enter an integer"+d.join(" and")+".",classes:["red"]}}};break;case "streamname":k=function(a,b){if(a!=""){if(!isNaN(a.charAt(0)))return{msg:"The first character may not be a number.", +-classes:["red"]};if(a.toLowerCase()!=a)return{msg:"Uppercase letters are not allowed.",classes:["red"]};if(a.replace(/[^\da-z_]/g,"")!=a)return{msg:"Special characters (except for underscores) are not allowed.",classes:["red"]};if("streams"in mist.data&&a in mist.data.streams&&$(b).data("pointer").main.name!=a)return{msg:"This streamname already exists.<br>If you want to edit an existing stream, please click edit on the the streams tab.",classes:["red"]}}};break;case "streamname_with_wildcard":k= +-function(a){if(a!=""){streampart=a.split("+");var b=streampart.slice(1).join("+");streampart=streampart[0];if(!isNaN(streampart.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(streampart.toLowerCase()!=streampart)return{msg:"Uppercase letters are not allowed in a stream name.",classes:["red"]};if(streampart.replace(/[^\da-z_]/g,"")!=streampart)return{msg:"Special characters (except for underscores) are not allowed in a stream name.",classes:["red"]};if(streampart!= +-a&&b.replace(/[\00|\0|\/]/g,"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;case "streamname_with_wildcard_and_variables":k=function(a){if(a!=""){streampart=a.split("+");var b=streampart.slice(1).join("+");streampart=streampart[0];if(!isNaN(streampart.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(streampart.toLowerCase()!=streampart)return{msg:"Uppercase letters are not allowed in a stream name.",classes:["red"]}; +-if(streampart.replace(/[^\da-z_$]/g,"")!=streampart)return{msg:"Special characters (except for underscores) are not allowed in a stream name.",classes:["red"]};if(streampart!=a&&b.replace(/[\00|\0|\/]/g,"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;default:k=function(){}}m.push(k)}e.data("validate_functions",m).data("help_container",f).data("validate",function(a,b){if($(a).is(":visible")||$(a).is('input[type="hidden"]')){var c=$(a).getval(),d=$(a).data("validate_functions"), +-g=$(a).data("help_container");g.find(".err_balloon").remove();for(var e in d){var i=d[e](c,a);if(i){$err=$("<span>").addClass("err_balloon").html(i.msg);for(var f in i.classes)$err.addClass(i.classes[f]);g.prepend($err);b&&$(a).focus();return typeof i=="object"&&"break"in i?i["break"]:true}}return false}}).addClass("hasValidate").on("change keyup",function(){$(this).data("validate")($(this))});""!=e.getval()&&e.trigger("change")}"function"in d&&(e.on("change keyup",d["function"]),e.trigger("change"))}}b.on("keydown", +-function(a){var b=!1;switch(a.which){case 13:b=$(this).find("button.save").first();break;case 27:b=$(this).find("button.cancel").first()}b&&b.length&&(b.trigger("click"),a.stopPropagation())});return b},buildVheaderTable:function(a){var b=$("<table>").css("margin","0.2em"),c=$("<tr>").addClass("header").append($("<td>").addClass("vheader").attr("rowspan",a.labels.length+1).append($("<span>").text(a.vheader))),d=[];c.append($("<td>"));for(var e in a.labels)d.push($("<tr>").append($("<td>").html(""== +-a.labels[e]?" ":a.labels[e]+":")));for(var l in a.content)for(e in c.append($("<td>").html(a.content[l].header)),a.content[l].body)d[e].append($("<td>").html(a.content[l].body[e]));b.append($("<tbody>").append(c).append(d));return b},plot:{addGraph:function(a,b){var c={id:a.id,xaxis:a.xaxis,datasets:[],elements:{cont:$("<div>").addClass("graph"),plot:$("<div>").addClass("plot"),legend:$("<div>").addClass("legend").attr("draggable","true")}};UI.draggable(c.elements.legend);c.elements.cont.append(c.elements.plot).append(c.elements.legend); ++menu:[{Overview:{},General:{},Protocols:{},Streams:{hiddenmenu:{Edit:{},Preview:{},Embed:{}}},Push:{},Triggers:{},Logs:{},Statistics:{},"Server Stats":{}},{Disconnect:{classes:["red"]}},{Guides:{link:"http://mistserver.org/documentation#Userdocs"},Tools:{submenu:{"Release notes":{link:"http://mistserver.org/documentation#Devdocs"},"Mist Shop":{link:"http://mistserver.org/products"},"Email for Help":{}}}}],buildMenu:function(){function a(a,b){var c=$("<a>").addClass("button");c.html($("<span>").addClass("plain").text(a)).append($("<span>").addClass("highlighted").text(a)); ++for(var d in b.classes)c.addClass(b.classes[d]);"link"in b?c.attr("href",b.link).attr("target","_blank"):"submenu"in b||c.click(function(b){$(this).closest(".menu").hasClass("hide")||(UI.navto(a),b.stopPropagation())});return c}var b=UI.elements.menu,c;for(c in UI.menu){0<c&&b.append($("<br>"));for(var d in UI.menu[c]){var e=UI.menu[c][d],l=a(d,e);b.append(l);if("submenu"in e){var n=$("<span>").addClass("submenu");l.addClass("arrowdown").append(n);for(var h in e.submenu)n.append(a(h,e.submenu[h]))}else if("hiddenmenu"in ++e)for(h in n=$("<span>").addClass("hiddenmenu"),l.append(n),e.hiddenmenu)n.append(a(h,e.hiddenmenu[h]))}}c=$("<div>").attr("id","ih_button").text("?").click(function(){$("body").toggleClass("helpme");UI.stored.saveOpt("helpme",$("body").hasClass("helpme"))}).attr("title","Click to toggle the display of integrated help");UI.stored.getOpts().helpme&&$("body").addClass("helpme");b.after(c).after($("<div>").addClass("separator"))},findInput:function(a){return this.findInOutput("inputs",a)},findOutput:function(a){return this.findInOutput("connectors", ++a)},findInOutput:function(a,b){if("capabilities"in mist.data){var c=!1,d=mist.data.capabilities[a];b in d&&(c=d[b]);b+".exe"in d&&(c=d[b+".exe"]);return c}throw"Request capabilities first";},buildUI:function(a){var b=$("<div>").addClass("input_container"),c;for(c in a){var d=a[c];if(d instanceof jQuery)b.append(d);else if("help"==d.type){var e=$("<span>").addClass("text_container").append($("<span>").addClass("description").append(d.help));b.append(e);if("classes"in d)for(var l in d.classes)e.addClass(d.classes[l])}else if("text"== ++d.type)b.append($("<span>").addClass("text_container").append($("<span>").addClass("text").append(d.text)));else if("custom"==d.type)b.append(d.custom);else if("buttons"==d.type)for(l in e=$("<span>").addClass("button_container").on("keydown",function(a){a.stopPropagation()}),"css"in d&&e.css(d.css),b.append(e),d.buttons){var n=d.buttons[l],h=$("<button>").text(n.label).data("opts",n);"css"in n&&h.css(n.css);if("classes"in n)for(var t in n.classes)h.addClass(n.classes[t]);e.append(h);switch(n.type){case "cancel":h.addClass("cancel").click(n["function"]); ++break;case "save":h.addClass("save").click(function(){var a=$(this).data("opts").preSave;a&&a.call(this);var b=$(this).closest(".input_container"),c=!1;b.find('.hasValidate:visible, input[type="hidden"].hasValidate').each(function(){if(c=$(this).data("validate")(this,!0))return!1});(a=$(this).data("opts").failedValidate)&&a.call(this);c||(b.find('.isSetting:visible, input[type="hidden"].isSetting').each(function(){var a=$(this).getval(),b=$(this).data("pointer");if(""===a)if("default"in $(this).data("opts"))a= ++$(this).data("opts")["default"];else return b.main[b.index]=null,!0;b.main[b.index]=a}),(a=$(this).data("opts")["function"])&&a(this))});break;default:h.click(n["function"])}}else{n=$("<label>").addClass("UIelement");b.append(n);"css"in d&&n.css(d.css);n.append($("<span>").addClass("label").html("label"in d?d.label+":":""));if("classes"in d)for(t in d.classes)n.addClass(d.classes[t]);h=$("<span>").addClass("field_container");n.append(h);switch(d.type){case "password":e=$("<input>").attr("type","password"); ++break;case "int":e=$("<input>").attr("type","number");"min"in d&&e.attr("min",d.min);"max"in d&&e.attr("max",d.max);"step"in d&&e.attr("step",d.step);"validate"in d?d.validate.push("int"):d.validate=["int"];break;case "span":e=$("<span>");break;case "debug":d.select=[["","Default"],[0,"0 - All debugging messages disabled"],[1,"1 - Messages about failed operations"],[2,"2 - Previous level, and error messages"],[3,"3 - Previous level, and warning messages"],[4,"4 - Previous level, and status messages for development"], ++[5,"5 - Previous level, and more status messages for development"],[6,"6 - Previous level, and verbose debugging messages"],[7,"7 - Previous level, and very verbose debugging messages"],[8,"8 - Report everything in extreme detail"],[9,"9 - Report everything in insane detail"],[10,"10 - All messages enabled"]];case "select":e=$("<select>");for(l in d.select){var m=$("<option>");"string"==typeof d.select[l]?m.text(d.select[l]):m.val(d.select[l][0]).text(d.select[l][1]);e.append(m)}break;case "textarea":e= ++$("<textarea>").on("keydown",function(a){a.stopPropagation()});break;case "checkbox":e=$("<input>").attr("type","checkbox");break;case "hidden":e=$("<input>").attr("type","hidden");n.hide();break;case "email":e=$("<input>").attr("type","email").attr("autocomplete","on").attr("required","");break;case "browse":e=$("<input>").attr("type","text");"filetypes"in d&&e.data("filetypes",d.filetypes);break;case "geolimited":case "hostlimited":e=$("<input>").attr("type","hidden");break;case "radioselect":e= ++$("<div>").addClass("radioselect");for(c in d.radioselect){var k=$("<input>").attr("type","radio").val(d.radioselect[c][0]).attr("name",d.label);d.readonly&&k.prop("disabled",!0);m=$("<label>").append(k).append($("<span>").html(d.radioselect[c][1]));e.append(m);if(2<d.radioselect[c].length)for(l in k=$("<select>").change(function(){$(this).parent().find("input[type=radio]:enabled").prop("checked","true")}),m.append(k),d.readonly&&k.prop("disabled",!0),d.radioselect[c][2])m=$("<option>"),k.append(m), ++d.radioselect[c][2][l]instanceof Array?m.val(d.radioselect[c][2][l][0]).html(d.radioselect[c][2][l][1]):m.html(d.radioselect[c][2][l])}break;case "checklist":e=$("<div>").addClass("checkcontainer");$controls=$("<div>").addClass("controls");$checklist=$("<div>").addClass("checklist");e.append($checklist);for(c in d.checklist)"string"==typeof d.checklist[c]&&(d.checklist[c]=[d.checklist[c],d.checklist[c]]),$checklist.append($("<label>").text(d.checklist[c][1]).prepend($("<input>").attr("type","checkbox").attr("name", ++d.checklist[c][0])));break;case "DOMfield":e=d.DOMfield;break;case "unix":e=$("<input>").attr("type","datetime-local").attr("step",1);d.unit=$("<button>").text("Now").click(function(){$(this).closest(".field_container").find(".field").setval((new Date).getTime()/1E3)});break;case "selectinput":e=$("<div>").addClass("selectinput");k=$("<select>");e.append(k);k.data("input",!1);for(c in d.selectinput)m=$("<option>"),k.append(m),"string"==typeof d.selectinput[c]?m.text(d.selectinput[c]):(m.text(d.selectinput[c][1]), ++"string"==typeof d.selectinput[c][0]?m.val(d.selectinput[c][0]):(m.val("CUSTOM"),k.data("input")||k.data("input",UI.buildUI([d.selectinput[c][0]]).children())));k.data("input")&&e.append(k.data("input"));k.change(function(){"CUSTOM"==$(this).val()?$(this).data("input").css("display","flex"):$(this).data("input").hide()});k.trigger("change");break;case "inputlist":e=$("<div>").addClass("inputlist");e.data("newitem",function(){var a=$("<input>").attr("type","text").addClass("listitem");d.readonly&& ++a.prop("disabled",!0);var b=function(c){$(this).is(":last-child")?""!=$(this).val()?$(this).after(a.clone().keyup(b).val("")):8==c.which&&$(this).prev().focus():""==$(this).val()&&($(this).next().focus(),$(this).remove())};a.keyup(b);return a});e.append(e.data("newitem"));break;case "sublist":e=$("<div>").addClass("sublist");k=$("<div>").addClass("curvals");k.append($("<span>").text("None."));var w=$("<div>").addClass("itemsettings"),i=$("<button>").text("New "+d.itemLabel),g=d.sublist,f=d,j=e,r= ++n;e.data("build",function(a,b){for(var c in f.saveas)c in a||delete f.saveas[c];f.saveas=Object.assign(f.saveas,a);c="New";"undefined"!=typeof b&&(c="Edit");c=UI.buildUI([$("<h4>").text(c+" "+f.itemLabel)].concat(g).concat([{label:"Save first",type:"str",classes:["onlyshowhelp"],validate:[function(){return{msg:"Did you want to save this "+f.itemLabel+"?",classes:["red"]}}]},{type:"buttons",buttons:[{label:"Cancel",type:"cancel","function":function(){w.html("");i.show();r.show()}},{label:"Save "+f.itemLabel, ++type:"save",preSave:function(){$(this).closest(".input_container").find(".onlyshowhelp").closest("label").hide()},failedValidate:function(){$(this).closest(".input_container").find(".onlyshowhelp").closest("label").show()},"function":function(){var a=j.getval(),c=Object.assign({},f.saveas),d;for(d in c)null===c[d]&&delete c[d];"undefined"==typeof b?a.push(c):a[b]=c;j.setval(a);w.html("");i.show();r.show()}}]}]));w.html(c);i.hide();r.hide()});var F=e;i.click(function(){F.data("build")({})});g.unshift({type:"str", ++label:"Human readable name",placeholder:"none",help:"A convenient name to describe this "+d.itemLabel+". It won't be used by MistServer.",pointer:{main:d.saveas,index:"x-LSP-name"}});e.data("savelist",[]);e.append(k).append(i);b.append(w);break;case "json":e=$("<textarea>").on("keydown",function(a){a.stopPropagation()}).on("keyup change",function(){this.style.height="";this.style.height=(this.scrollHeight?this.scrollHeight+20:14*this.value.split("\n").length+20)+"px"}).css("min-height","3em");k=function(a, ++b){if(""!=$(b).val()&&null===a)return{msg:"Invalid json",classes:["red"]}};"validate"in d?d.validate.push(k):d.validate=[k];break;case "bitmask":e=$("<div>").addClass("bitmask");for(c in d.bitmask)e.append($("<label>").append($("<input>").attr("type","checkbox").attr("name","bitmask_"+("pointer"in d?d.pointer.index:"")).attr("value",d.bitmask[c][0]).addClass("field")).append($("<span>").text(d.bitmask[c][1])));n.attr("for","none");break;default:e=$("<input>").attr("type","text")}e.addClass("field").data("opts", ++d);"pointer"in d&&e.attr("name",d.pointer.index);h.append(e);if("classes"in d)for(l in d.classes)e.addClass(d.classes[l]);"placeholder"in d&&e.attr("placeholder",d.placeholder);"default"in d&&e.attr("placeholder",d["default"]);"unit"in d&&h.append($("<span>").addClass("unit").html(d.unit));"readonly"in d&&(e.attr("readonly","readonly"),e.click(function(){$(this).select()}));"qrcode"in d&&h.append($("<span>").addClass("unit").html($("<button>").text("QR").on("keydown",function(a){a.stopPropagation()}).click(function(){var a= ++String($(this).closest(".field_container").find(".field").getval()),b=$("<div>").addClass("qrcode");UI.popup.show($("<span>").addClass("qr_container").append($("<p>").text(a)).append(b));b.qrcode({text:a,size:Math.min(b.width(),b.height())})})));"clipboard"in d&&document.queryCommandSupported("copy")&&h.append($("<span>").addClass("unit").html($("<button>").text("Copy").on("keydown",function(a){a.stopPropagation()}).click(function(){var a=String($(this).closest(".field_container").find(".field").getval()), ++b=document.createElement("textarea");b.value=a;document.body.appendChild(b);b.select();var c=false;try{c=document.execCommand("copy")}catch(d){}if(c){$(this).text("Copied to clipboard!");document.body.removeChild(b);var g=$(this);setTimeout(function(){g.text("Copy")},5E3)}else{document.body.removeChild(b);alert("Failed to copy:\n"+a)}})));"rows"in d&&e.attr("rows",d.rows);if("dependent"in d)for(c in d.dependent)n.attr("data-dependent-"+c,d.dependent[c]);switch(d.type){case "browse":k=$("<div>").addClass("grouper").append(n); ++b.append(k);k=$("<button>").text("Browse").on("keydown",function(a){a.stopPropagation()});h.append(k);k.click(function(){function a(b){h.text("Loading..");mist.send(function(a){e.text(a.browse.path[0]);mist.data.LTS&&d.setval(a.browse.path[0]+"/");h.html(i.clone(true).text("..").attr("title","Folder up"));if(a.browse.subdirectories){a.browse.subdirectories.sort();for(var b in a.browse.subdirectories){var f=a.browse.subdirectories[b];h.append(i.clone(true).attr("title",e.text()+n+f).text(f))}}if(a.browse.files){a.browse.files.sort(); ++for(b in a.browse.files){var f=a.browse.files[b],k=e.text()+n+f,f=$("<a>").text(f).addClass("file").attr("title",k);h.append(f);if(j){var l=true,m;for(m in j)if(typeof j[m]!="undefined"&&mist.inputMatch(j[m],k)){l=false;break}l&&f.hide()}f.click(function(){var a=$(this).attr("title");d.setval(a).removeAttr("readonly").css("opacity",1);g.show();c.remove()})}}},{browse:b})}var b=$(this).closest(".grouper"),c=$("<div>").addClass("browse_container"),d=b.find(".field").attr("readonly","readonly").css("opacity", ++0.5),g=$(this),f=$("<button>").text("Stop browsing").click(function(){g.show();c.remove();d.removeAttr("readonly").css("opacity",1)}),e=$("<span>").addClass("field"),h=$("<div>").addClass("browse_contents"),i=$("<a>").addClass("folder"),j=d.data("filetypes");b.append(c);c.append($("<label>").addClass("UIelement").append($("<span>").addClass("label").text("Current folder:")).append($("<span>").addClass("field_container").append(e).append(f))).append(h);var n="/";mist.data.config.version.indexOf("indows")> ++-1&&(n="\\");i.click(function(){var b=e.text()+n+$(this).text();a(b)});b=d.getval();f=b.split("://");f.length>1&&(b=f[0]=="file"?f[1]:"");b=b.split(n);b.pop();b=b.join(n);g.hide();a(b)});break;case "geolimited":case "hostlimited":k={field:e};k.blackwhite=$("<select>").append($("<option>").val("-").text("Blacklist")).append($("<option>").val("+").text("Whitelist"));k.values=$("<span>").addClass("limit_value_list");switch(d.type){case "geolimited":k.prototype=$("<select>").append($("<option>").val("").text("[Select a country]")); ++for(c in UI.countrylist)k.prototype.append($("<option>").val(c).html(UI.countrylist[c]));break;case "hostlimited":k.prototype=$("<input>").attr("type","text").attr("placeholder","type a host")}k.prototype.on("change keyup",function(){$(this).closest(".field_container").data("subUI").blackwhite.trigger("change")});k.blackwhite.change(function(){var a=$(this).closest(".field_container").data("subUI"),b=[],c=false;a.values.children().each(function(){c=$(this).val();c!=""?b.push(c):$(this).remove()}); ++a.values.append(a.prototype.clone(true));b.length>0?a.field.val($(this).val()+b.join(" ")):a.field.val("");a.field.trigger("change")});k.values.append(k.prototype.clone(!0));h.data("subUI",k).addClass("limit_list").append(k.blackwhite).append(k.values)}"pointer"in d&&(e.data("pointer",d.pointer).addClass("isSetting"),d.pointer.main&&(k=d.pointer.main[d.pointer.index],"undefined"!=k&&e.setval(k)));(""==e.getval()||null==e.getval())&&"value"in d&&e.setval(d.value);if("datalist"in d)for(c in k="datalist_"+ ++c+MD5(e[0].outerHTML),e.attr("list",k),k=$("<datalist>").attr("id",k),h.append(k),d.datalist)k.append($("<option>").val(d.datalist[c]));h=$("<span>").addClass("help_container");n.append(h);"help"in d&&(h.append($("<span>").addClass("ih_balloon").html(d.help)),e.on("focus mouseover",function(){$(this).closest("label").addClass("active")}).on("blur mouseout",function(){$(this).closest("label").removeClass("active")}));if("validate"in d){n=[];for(l in d.validate){k=d.validate[l];if("function"!=typeof k)switch(k){case "required":k= ++function(a){return a==""||a==null?{msg:"This is a required field.",classes:["red"]}:false};break;case "int":k=function(a,b){var c=$(b).data("opts");if(!$(b)[0].validity.valid){var d=[];"min"in c&&d.push(" greater than or equal to "+c.min);"max"in c&&d.push(" smaller than or equal to "+c.max);return{msg:"Please enter an integer"+d.join(" and")+".",classes:["red"]}}};break;case "streamname":k=function(a,b){if(a!=""){if(!isNaN(a.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]}; ++if(a.toLowerCase()!=a)return{msg:"Uppercase letters are not allowed.",classes:["red"]};if(a.replace(/[^\da-z_]/g,"")!=a)return{msg:"Special characters (except for underscores) are not allowed.",classes:["red"]};if("streams"in mist.data&&a in mist.data.streams&&$(b).data("pointer").main.name!=a)return{msg:"This streamname already exists.<br>If you want to edit an existing stream, please click edit on the the streams tab.",classes:["red"]}}};break;case "streamname_with_wildcard":k=function(a){if(a!= ++""){streampart=a.split("+");var b=streampart.slice(1).join("+");streampart=streampart[0];if(!isNaN(streampart.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(streampart.toLowerCase()!=streampart)return{msg:"Uppercase letters are not allowed in a stream name.",classes:["red"]};if(streampart.replace(/[^\da-z_]/g,"")!=streampart)return{msg:"Special characters (except for underscores) are not allowed in a stream name.",classes:["red"]};if(streampart!=a&&b.replace(/[\00|\0|\/]/g, ++"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;case "streamname_with_wildcard_and_variables":k=function(a){if(a!=""){streampart=a.split("+");var b=streampart.slice(1).join("+");streampart=streampart[0];if(!isNaN(streampart.charAt(0)))return{msg:"The first character may not be a number.",classes:["red"]};if(streampart.toLowerCase()!=streampart)return{msg:"Uppercase letters are not allowed in a stream name.",classes:["red"]};if(streampart.replace(/[^\da-z_$]/g, ++"")!=streampart)return{msg:"Special characters (except for underscores) are not allowed in a stream name.",classes:["red"]};if(streampart!=a&&b.replace(/[\00|\0|\/]/g,"")!=b)return{msg:"Slashes or null bytes are not allowed in wildcards.",classes:["red"]}}};break;default:k=function(){}}n.push(k)}e.data("validate_functions",n).data("help_container",h).data("validate",function(a,b){if($(a).is(":visible")||$(a).is('input[type="hidden"]')){var c=$(a).getval(),d=$(a).data("validate_functions"),g=$(a).data("help_container"); ++g.find(".err_balloon").remove();for(var f in d){var e=d[f](c,a);if(e){$err=$("<span>").addClass("err_balloon").html(e.msg);for(var h in e.classes)$err.addClass(e.classes[h]);g.prepend($err);b&&$(a).focus();return typeof e=="object"&&"break"in e?e["break"]:true}}return false}}).addClass("hasValidate").on("change keyup",function(){$(this).data("validate")($(this))});""!=e.getval()&&e.trigger("change")}"function"in d&&(e.on("change keyup",d["function"]),e.trigger("change"))}}b.on("keydown",function(a){var b= ++!1;switch(a.which){case 13:b=$(this).find("button.save").first();break;case 27:b=$(this).find("button.cancel").first()}b&&b.length&&(b.trigger("click"),a.stopPropagation())});return b},buildVheaderTable:function(a){var b=$("<table>").css("margin","0.2em"),c=$("<tr>").addClass("header").append($("<td>").addClass("vheader").attr("rowspan",a.labels.length+1).append($("<span>").text(a.vheader))),d=[];c.append($("<td>"));for(var e in a.labels)d.push($("<tr>").append($("<td>").html(""==a.labels[e]?" ": ++a.labels[e]+":")));for(var l in a.content)for(e in c.append($("<td>").html(a.content[l].header)),a.content[l].body)d[e].append($("<td>").html(a.content[l].body[e]));b.append($("<tbody>").append(c).append(d));return b},plot:{addGraph:function(a,b){var c={id:a.id,xaxis:a.xaxis,datasets:[],elements:{cont:$("<div>").addClass("graph"),plot:$("<div>").addClass("plot"),legend:$("<div>").addClass("legend").attr("draggable","true")}};UI.draggable(c.elements.legend);c.elements.cont.append(c.elements.plot).append(c.elements.legend); + b.append(c.elements.cont);return c},go:function(a){if(!(1>Object.keys(a).length)){var b={totals:[],clients:[]},c;for(c in a)for(var d in a[c].datasets){var e=a[c].datasets[d];switch(e.datatype){case "clients":case "upbps":case "downbps":case "perc_lost":case "perc_retrans":switch(e.origin[0]){case "total":b.totals.push({fields:[e.datatype],end:-15});break;case "stream":b.totals.push({fields:[e.datatype],streams:[e.origin[1]],end:-15});break;case "protocol":b.totals.push({fields:[e.datatype],protocols:[e.origin[1]], +-end:-15})}break;case "cpuload":case "memload":b.capabilities={}}}0==b.totals.length&&delete b.totals;0==b.clients.length&&delete b.clients;mist.send(function(){for(var b in a){var c=a[b];if(1>c.datasets.length){c.elements.plot.html("");c.elements.legend.html("");break}switch(c.xaxis){case "time":var d=[];c.yaxes={};var e=[],o;for(o in c.datasets){var k=c.datasets[o];k.display&&(k.getdata(),k.yaxistype in c.yaxes||(d.push(UI.plot.yaxes[k.yaxistype]),c.yaxes[k.yaxistype]=d.length),k.yaxis=c.yaxes[k.yaxistype], ++end:-15})}break;case "cpuload":case "memload":b.capabilities={}}}0==b.totals.length&&delete b.totals;0==b.clients.length&&delete b.clients;mist.send(function(){for(var b in a){var c=a[b];if(1>c.datasets.length){c.elements.plot.html("");c.elements.legend.html("");break}switch(c.xaxis){case "time":var d=[];c.yaxes={};var e=[],m;for(m in c.datasets){var k=c.datasets[m];k.display&&(k.getdata(),k.yaxistype in c.yaxes||(d.push(UI.plot.yaxes[k.yaxistype]),c.yaxes[k.yaxistype]=d.length),k.yaxis=c.yaxes[k.yaxistype], + e.push(k))}d[0]&&(d[0].color=0);c.plot=$.plot(c.elements.plot,e,{legend:{show:!1},xaxis:UI.plot.xaxes[c.xaxis],yaxes:d,grid:{hoverable:!0,borderWidth:{top:0,right:0,bottom:1,left:1},color:"black",backgroundColor:{colors:["rgba(0,0,0,0)","rgba(0,0,0,0.025)"]}},crosshair:{mode:"x"}});d=$("<table>").addClass("legend-list").addClass("nolay").html($("<tr>").html($("<td>").html($("<h3>").text(c.id))).append($("<td>").css("padding-right","2em").css("text-align","right").html($("<span>").addClass("value")).append($("<button>").data("opts", + c).text("X").addClass("close").click(function(){var b=$(this).data("opts");if(confirm("Are you sure you want to remove "+b.id+"?")){b.elements.cont.remove();var c=$(".graph_ids option:contains("+b.id+")"),d=c.parent();c.remove();UI.plot.del(b.id);delete a[b.id];d.trigger("change");UI.plot.go(a)}}))));c.elements.legend.html(d);var w=function(a){var b=c.elements.legend.find(".value"),d=1;if(typeof a=="undefined")b.eq(0).html("Latest:");else{var e=c.plot.getXAxes()[0],a=Math.min(e.max,a),a=Math.max(e.min, +-a);b.eq(0).html(UI.format.time(a/1E3))}for(var f in c.datasets){var h=" ";if(c.datasets[f].display){var e=UI.plot.yaxes[c.datasets[f].yaxistype].tickFormatter,k=c.datasets[f].data;if(a)for(var l in k){if(k[l][0]==a){h=e(k[l][1]);break}if(k[l][0]>a){if(l!=0){h=k[l];k=k[l-1];h=e(h[1]+(a-h[0])*(k[1]-h[1])/(k[0]-h[0]))}break}}else h=e(c.datasets[f].data[c.datasets[f].data.length-1][1])}b.eq(d).html(h);d++}};c.plot.getOptions();for(o in c.datasets)e=$("<input>").attr("type","checkbox").data("index", +-o).data("graph",c).click(function(){var a=$(this).data("graph");$(this).is(":checked")?a.datasets[$(this).data("index")].display=true:a.datasets[$(this).data("index")].display=false;var b={};b[a.id]=a;UI.plot.go(b)}),c.datasets[o].display&&e.attr("checked","checked"),d.append($("<tr>").html($("<td>").html($("<label>").html(e).append($("<div>").addClass("series-color").css("background-color",c.datasets[o].color)).append(c.datasets[o].label))).append($("<td>").css("padding-right","2em").css("text-align", +-"right").html($("<span>").addClass("value")).append($("<button>").text("X").addClass("close").data("index",o).data("graph",c).click(function(){var b=$(this).data("index"),c=$(this).data("graph");if(confirm("Are you sure you want to remove "+c.datasets[b].label+" from "+c.id+"?")){c.datasets.splice(b,1);if(c.datasets.length==0){c.elements.cont.remove();var b=$(".graph_ids option:contains("+c.id+")"),d=b.parent();b.remove();d.trigger("change");UI.plot.del(c.id);delete a[c.id];UI.plot.go(a)}else{UI.plot.save(c); +-b={};b[c.id]=c;UI.plot.go(b)}}}))));w();var h=!1;c.elements.plot.on("plothover",function(a,b,c){if(b.x!=h){w(b.x);h=b.x}if(c){a=$("<span>").append($("<h3>").text(c.series.label).prepend($("<div>").addClass("series-color").css("background-color",c.series.color))).append($("<table>").addClass("nolay").html($("<tr>").html($("<td>").text("Time:")).append($("<td>").html(UI.format.dateTime(c.datapoint[0]/1E3,"long")))).append($("<tr>").html($("<td>").text("Value:")).append($("<td>").html(c.series.yaxis.tickFormatter(c.datapoint[1], ++a);b.eq(0).html(UI.format.time(a/1E3))}for(var h in c.datasets){var i=" ";if(c.datasets[h].display){var e=UI.plot.yaxes[c.datasets[h].yaxistype].tickFormatter,k=c.datasets[h].data;if(a)for(var l in k){if(k[l][0]==a){i=e(k[l][1]);break}if(k[l][0]>a){if(l!=0){i=k[l];k=k[l-1];i=e(i[1]+(a-i[0])*(k[1]-i[1])/(k[0]-i[0]))}break}}else i=e(c.datasets[h].data[c.datasets[h].data.length-1][1])}b.eq(d).html(i);d++}};c.plot.getOptions();for(m in c.datasets)e=$("<input>").attr("type","checkbox").data("index", ++m).data("graph",c).click(function(){var a=$(this).data("graph");$(this).is(":checked")?a.datasets[$(this).data("index")].display=true:a.datasets[$(this).data("index")].display=false;var b={};b[a.id]=a;UI.plot.go(b)}),c.datasets[m].display&&e.attr("checked","checked"),d.append($("<tr>").html($("<td>").html($("<label>").html(e).append($("<div>").addClass("series-color").css("background-color",c.datasets[m].color)).append(c.datasets[m].label))).append($("<td>").css("padding-right","2em").css("text-align", ++"right").html($("<span>").addClass("value")).append($("<button>").text("X").addClass("close").data("index",m).data("graph",c).click(function(){var b=$(this).data("index"),c=$(this).data("graph");if(confirm("Are you sure you want to remove "+c.datasets[b].label+" from "+c.id+"?")){c.datasets.splice(b,1);if(c.datasets.length==0){c.elements.cont.remove();var b=$(".graph_ids option:contains("+c.id+")"),d=b.parent();b.remove();d.trigger("change");UI.plot.del(c.id);delete a[c.id];UI.plot.go(a)}else{UI.plot.save(c); ++b={};b[c.id]=c;UI.plot.go(b)}}}))));w();var i=!1;c.elements.plot.on("plothover",function(a,b,c){if(b.x!=i){w(b.x);i=b.x}if(c){a=$("<span>").append($("<h3>").text(c.series.label).prepend($("<div>").addClass("series-color").css("background-color",c.series.color))).append($("<table>").addClass("nolay").html($("<tr>").html($("<td>").text("Time:")).append($("<td>").html(UI.format.dateTime(c.datapoint[0]/1E3,"long")))).append($("<tr>").html($("<td>").text("Value:")).append($("<td>").html(c.series.yaxis.tickFormatter(c.datapoint[1], + c.series.yaxis)))));UI.tooltip.show(b,a.children())}else UI.tooltip.hide()}).on("mouseout",function(){w()})}}},b)}},save:function(a){var b={id:a.id,xaxis:a.xaxis,datasets:[]},c;for(c in a.datasets)b.datasets.push({origin:a.datasets[c].origin,datatype:a.datasets[c].datatype});a=mist.stored.get().graphs||{};a[b.id]=b;mist.stored.set("graphs",a)},del:function(a){var b=mist.stored.get().graphs||{};delete b[a];mist.stored.set("graphs",b)},datatype:{getOptions:function(a){var b=$.extend(!0,{},UI.plot.datatype.templates.general), + c=$.extend(!0,{},UI.plot.datatype.templates[a.datatype]),a=$.extend(!0,c,a),a=$.extend(!0,b,a);switch(a.origin[0]){case "total":switch(a.datatype){case "cpuload":case "memload":break;default:a.label+=" (total)"}break;case "stream":case "protocol":a.label+=" ("+a.origin[1]+")"}var b=[],d;for(d in a.basecolor)c=a.basecolor[d],c+=50*(0.5-Math.random()),c=Math.round(c),c=Math.min(255,Math.max(0,c)),b.push(c);a.color="rgb("+b.join(",")+")";return a},templates:{general:{display:!0,datatype:"general",label:"", + yaxistype:"amount",data:[],lines:{show:!0},points:{show:!1},getdata:function(){var a=mist.data.totals["stream"==this.origin[0]?this.origin[1]:"all_streams"]["protocol"==this.origin[0]?this.origin[1]:"all_protocols"][this.datatype];return this.data=a}},cpuload:{label:"CPU use",yaxistype:"percentage",basecolor:[237,194,64],cores:1,getdata:function(){var a=!1,b;for(b in this.data)this.data[b][0]<1E3*(mist.data.config.time-600)&&(a=b);!1!==a&&this.data.splice(0,Number(a)+1);this.data.push([1E3*mist.data.config.time, + mist.data.capabilities.cpu_use/10]);return this.data}},memload:{label:"Memory load",yaxistype:"percentage",basecolor:[175,216,248],getdata:function(){var a=!1,b;for(b in this.data)this.data[b][0]<1E3*(mist.data.config.time-600)&&(a=b);!1!==a&&this.data.splice(0,Number(a)+1);this.data.push([1E3*mist.data.config.time,mist.data.capabilities.load.memory]);return this.data}},clients:{label:"Connections",basecolor:[203,75,75]},upbps:{label:"Bandwidth up",yaxistype:"bytespersec",basecolor:[77,167,77]},downbps:{label:"Bandwidth down", + yaxistype:"bytespersec",basecolor:[148,64,237]},perc_lost:{label:"Lost packages",yaxistype:"percentage",basecolor:[255,33,234]},perc_retrans:{label:"Re-transmitted packages",yaxistype:"percentage",basecolor:[0,0,255]}}},yaxes:{percentage:{name:"percentage",color:"black",tickColor:0,tickDecimals:0,tickFormatter:function(a){return UI.format.addUnit(UI.format.number(a),"%")},tickLength:0,min:0,max:100},amount:{name:"amount",color:"black",tickColor:0,tickDecimals:0,tickFormatter:function(a){return UI.format.number(a)}, +-tickLength:0,min:0},bytespersec:{name:"bytespersec",color:"black",tickColor:0,tickDecimals:1,tickFormatter:function(a){return UI.format.bytes(a,!0)},tickLength:0,ticks:function(a){var b=0.3*Math.sqrt($(".graph").first().height()),b=(a.max-a.min)/b,c=Math.floor(Math.log(Math.abs(b))/Math.log(1024)),d=b/Math.pow(1024,c),e=-Math.floor(Math.log(d)/Math.LN10),l=a.tickDecimals;null!=l&&e>l&&(e=l);var m=Math.pow(10,-e),d=d/m,f;if(1.5>d)f=1;else if(3>d){if(f=2,2.25<d&&(null==l||e+1<=l))f=2.5,++e}else f=7.5> +-d?5:10;f=f*m*Math.pow(1024,c);null!=a.minTickSize&&f<a.minTickSize&&(f=a.minTickSize);a.delta=b;a.tickDecimals=Math.max(0,null!=l?l:e);a.tickSize=f;b=[];c=a.tickSize*Math.floor(a.min/a.tickSize);e=0;l=Number.NaN;do m=l,l=c+e*a.tickSize,b.push(l),++e;while(l<a.max&&l!=m);return b},min:0}},xaxes:{time:{name:"time",mode:"time",timezone:"browser",ticks:5}}},draggable:function(a){a.attr("draggable",!0);a.on("dragstart",function(a){$(this).css("opacity",0.4).data("dragstart",{click:{x:a.originalEvent.pageX, ++tickLength:0,min:0},bytespersec:{name:"bytespersec",color:"black",tickColor:0,tickDecimals:1,tickFormatter:function(a){return UI.format.bytes(a,!0)},tickLength:0,ticks:function(a){var b=0.3*Math.sqrt($(".graph").first().height()),b=(a.max-a.min)/b,c=Math.floor(Math.log(Math.abs(b))/Math.log(1024)),d=b/Math.pow(1024,c),e=-Math.floor(Math.log(d)/Math.LN10),l=a.tickDecimals;null!=l&&e>l&&(e=l);var n=Math.pow(10,-e),d=d/n,h;if(1.5>d)h=1;else if(3>d){if(h=2,2.25<d&&(null==l||e+1<=l))h=2.5,++e}else h=7.5> ++d?5:10;h=h*n*Math.pow(1024,c);null!=a.minTickSize&&h<a.minTickSize&&(h=a.minTickSize);a.delta=b;a.tickDecimals=Math.max(0,null!=l?l:e);a.tickSize=h;b=[];c=a.tickSize*Math.floor(a.min/a.tickSize);e=0;l=Number.NaN;do n=l,l=c+e*a.tickSize,b.push(l),++e;while(l<a.max&&l!=n);return b},min:0}},xaxes:{time:{name:"time",mode:"time",timezone:"browser",ticks:5}}},draggable:function(a){a.attr("draggable",!0);a.on("dragstart",function(a){$(this).css("opacity",0.4).data("dragstart",{click:{x:a.originalEvent.pageX, + y:a.originalEvent.pageY},ele:{x:this.offsetLeft,y:this.offsetTop}})}).on("dragend",function(a){var c=$(this).data("dragstart"),d=c.ele.x-c.click.x+a.originalEvent.pageX,a=c.ele.y-c.click.y+a.originalEvent.pageY;$(this).css({opacity:1,top:a,left:d,right:"auto",bottom:"auto"})});a.parent().on("dragleave",function(){})},format:{time:function(a,b){var c=new Date(1E3*a),d=[];d.push(("0"+c.getHours()).slice(-2));d.push(("0"+c.getMinutes()).slice(-2));"short"!=b&&d.push(("0"+c.getSeconds()).slice(-2));return d.join(":")}, + date:function(a,b){var c=new Date(1E3*a),d="Sun Mon Tue Wed Thu Fri Sat".split(" "),e=[];"long"==b&&e.push(d[c.getDay()]);e.push(("0"+c.getDate()).slice(-2));e.push("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")[c.getMonth()]);"short"!=b&&e.push(c.getFullYear());return e.join(" ")},dateTime:function(a,b){return UI.format.date(a,b)+", "+UI.format.time(a,b)},duration:function(a){var b=[0.001,1E3,60,60,24,7,52,1E9],c="ms sec min hr day week year".split(" "),d={},e;for(e in c){var a=a/b[e], +-l=Math.round(a%b[Number(e)+1]);d[c[e]]=l;a-=l}var m;for(e=c.length-1;0<=e;e--)if(0<d[c[e]]){m=c[e];break}b=$("<span>");switch(m){case "year":b.append(UI.format.addUnit(d.year,"years, ")).append(UI.format.addUnit(d.week,"wks"));break;case "week":b.append(UI.format.addUnit(d.week,"wks, ")).append(UI.format.addUnit(d.day,"days"));break;case "day":b.append(UI.format.addUnit(d.day,"days, ")).append(UI.format.addUnit(d.hr,"hrs"));break;default:b.append([("0"+d.hr).slice(-2),("0"+d.min).slice(-2),("0"+d.sec).slice(-2)+ ++l=Math.round(a%b[Number(e)+1]);d[c[e]]=l;a-=l}var n;for(e=c.length-1;0<=e;e--)if(0<d[c[e]]){n=c[e];break}b=$("<span>");switch(n){case "year":b.append(UI.format.addUnit(d.year,"years, ")).append(UI.format.addUnit(d.week,"wks"));break;case "week":b.append(UI.format.addUnit(d.week,"wks, ")).append(UI.format.addUnit(d.day,"days"));break;case "day":b.append(UI.format.addUnit(d.day,"days, ")).append(UI.format.addUnit(d.hr,"hrs"));break;default:b.append([("0"+d.hr).slice(-2),("0"+d.min).slice(-2),("0"+d.sec).slice(-2)+ + (d.ms?"."+d.ms:"")].join(":"))}return b[0].innerHTML},number:function(a){if(isNaN(Number(a))||0==a)return a;var b=Math.pow(10,3-Math.floor(Math.log(a)/Math.LN10)-1),a=Math.round(a*b)/b;if(1E4<=a){number=a.toString().split(".");for(a=/(\d+)(\d{3})/;a.test(number[0]);)number[0]=number[0].replace(a,"$1 $2");a=number.join(".")}return a},status:function(a){var b=$("<span>");if("undefined"==typeof a.online)return b.text("Unknown, checking.."),"undefined"!=typeof a.error&&b.text(a.error),b;switch(a.online){case -1:b.text("Enabling"); + break;case 0:b.text("Unavailable").addClass("red");break;case 1:b.text("Active").addClass("green");break;case 2:b.text("Standby").addClass("orange");break;default:b.text(a.online)}"error"in a&&b.text(a.error);return b},capital:function(a){return a.charAt(0).toUpperCase()+a.substring(1)},addUnit:function(a,b){var c=$("<span>").html(a);c.append($("<span>").addClass("unit").html(b));return c[0].innerHTML},bytes:function(a,b){var c="bytes KiB MiB GiB TiB PiB".split(" ");if(0==a)unit=c[0];else{var d=Math.floor(Math.log(Math.abs(a))/ + Math.log(1024));0>d?unit=c[0]:(a/=Math.pow(1024,d),unit=c[d])}return UI.format.addUnit(UI.format.number(a),unit+(b?"/s":""))}},navto:function(a,b){var c=location.hash,d=c.split("@");d[0]=[mist.user.name,mist.user.host].join("&");d[1]=[a,b].join("&");"undefined"!=typeof screenlog&&screenlog.navto(d[1]);location.hash=d.join("@");location.hash==c&&$(window).trigger("hashchange")},showTab:function(a,b){var c=UI.elements.main;if(mist.user.loggedin){if(!("ui_settings"in mist.data)){c.html("Loading.."); +@@ -86,165 +86,171 @@ pointer:{main:mist.user,index:"name"}},{label:"Desired password",type:"password" + classes:["red"]}:false}],help:"Repeat your desired password.",classes:["match_password"]},{type:"buttons",buttons:[{type:"save",label:"Create new account","function":function(){mist.send(function(){UI.navto("Account created")},{authorize:{new_username:mist.user.name,new_password:mist.user.rawpassword}});mist.user.password=MD5(mist.user.rawpassword);delete mist.user.rawpassword}}]}]));break;case "Account created":UI.elements.menu.addClass("hide");c.append($("<p>").text("Your account has been created succesfully.")).append(UI.buildUI([{type:"text", + text:"Would you like to enable all (currently) available protocols with their default settings?"},{type:"buttons",buttons:[{label:"Enable protocols",type:"save","function":function(){if(mist.data.config.protocols)c.append("Unable to enable all protocols as protocol settings already exist.<br>");else{c.append("Retrieving available protocols..<br>");mist.send(function(a){var b=[],d;for(d in a.capabilities.connectors)if(a.capabilities.connectors[d].required)c.append('Could not enable protocol "'+d+'" because it has required settings.<br>'); + else{b.push({connector:d});c.append('Enabled protocol "'+d+'".<br>')}c.append("Saving protocol settings..<br>");mist.send(function(){c.append("Protocols enabled. Redirecting..");setTimeout(function(){UI.navto("Overview")},5E3)},{config:{protocols:b}})},{capabilities:true})}}},{label:"Skip",type:"cancel","function":function(){UI.navto("Overview")}}]}]));break;case "Overview":if("undefined"==typeof mist.data.bandwidth){mist.send(function(){UI.navto(a)},{bandwidth:!0});c.append("Loading..");return}var e= +-$("<span>").text("Loading.."),l=$("<span>"),m=$("<span>").addClass("logs"),f=$("<span>"),t=$("<span>"),o=$("<span>").text("Unknown"),k=$("<span>"),w=$("<span>"),h={serverid:mist.data.config.serverid,debug:mist.data.config.debug,accesslog:mist.data.config.accesslog,prometheus:mist.data.config.prometheus,defaultStream:mist.data.config.defaultStream,trustedproxy:mist.data.config.trustedproxy,location:"location"in mist.data.config?mist.data.config.location:{}},g={};"bandwidth"in mist.data&&(g=mist.data.bandwidth, +-null==g&&(g={}),g.limit||(g.limit=""));var i=$("<select>").html($("<option>").val(1).text("bytes/s")).append($("<option>").val(1024).text("KiB/s")).append($("<option>").val(1048576).text("MiB/s")).append($("<option>").val(1073741824).text("GiB/s")),j=parseURL(mist.user.host),j=j.protocol+j.host+j.port;c.append(UI.buildUI([{type:"help",help:"You can find most basic information about your MistServer here.<br>You can also set the debug level and force a save to the config.json file that MistServer uses to save your settings. "}, +-{type:"span",label:"Version",pointer:{main:mist.data.config,index:"version"}},{type:"span",label:"Version check",value:e,LTSonly:!0},{type:"span",label:"Server time",value:t},{type:"span",label:"Licensed to",value:"license"in mist.data.config?mist.data.config.license.user:"",LTSonly:!0},{type:"span",label:"Active licenses",value:o,LTSonly:!0},{type:"span",label:"Configured streams",value:mist.data.streams?Object.keys(mist.data.streams).length:0},{type:"span",label:"Active streams",value:l},{type:"span", +-label:"Current connections",value:f},{type:"span",label:"Enabled protocols",value:k},{type:"span",label:"Disabled protocols",value:w},{type:"span",label:"Recent problems",value:m},$("<br>"),{type:"str",label:"Human readable name",pointer:{main:h,index:"serverid"},help:"You can name your MistServer here for personal use. You'll still need to set host name within your network yourself."},{type:"debug",label:"Debug level",pointer:{main:h,index:"debug"},help:"You can set the amount of debug information MistServer saves in the log. A full reboot of MistServer is required before some components of MistServer can post debug information."}, +-{type:"selectinput",label:"Access log",selectinput:[["","Do not track"],["LOG","Log to MistServer log"],[{type:"str",label:"Path",LTSonly:!0},"Log to file"]],pointer:{main:h,index:"accesslog"},help:"Enable access logs.",LTSonly:!0},{type:"selectinput",label:"Prometheus stats output",selectinput:[["","Disabled"],[{type:"str",label:"Passphrase",LTSonly:!0},"Enabled"]],pointer:{main:h,index:"prometheus"},help:"Make stats available in Prometheus format. These can be accessed via "+j+"/PASSPHRASE or "+ +-j+"/PASSPHRASE.json.",LTSonly:!0},{type:"inputlist",label:"Trusted proxies",help:"List of proxy server addresses that are allowed to override the viewer IP address to arbitrary values.<br>You may use a hostname or IP address.",LTSonly:!0,pointer:{main:h,index:"trustedproxy"}},{type:"selectinput",label:"Load balancer bandwidth limit",selectinput:[["","Default (1 gbps)"],[{label:"Custom",type:"int",min:0,unit:i},"Custom"]],pointer:{main:g,index:"limit"},help:"This setting only applies when MistServer is combined with a load balancer. This is the amount of traffic this server is willing to handle.", +-LTSonly:!0},{type:"inputlist",label:"Load balancer bandwidth exceptions",pointer:{main:g,index:"exceptions"},help:"This setting only applies when MistServer is combined with a load balancer. Data sent to the hosts and subnets listed here will not count towards reported bandwidth usage.<br>Examples:<ul><li>192.168.0.0/16</li><li>localhost</li><li>10.0.0.0/8</li><li>fe80::/16</li></ul>",LTSonly:!0},{type:"int",step:1E-8,label:"Server latitude",pointer:{main:h.location,index:"lat"},help:"This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them.", +-LTSonly:!0},{type:"int",step:1E-8,label:"Server longitude",pointer:{main:h.location,index:"lon"},help:"This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them.",LTSonly:!0},{type:"str",label:"Server location name",pointer:{main:h.location,index:"name"},help:"This setting is only useful when MistServer is combined with a load balancer. This will be displayed as the server's location.",LTSonly:!0},{type:"str", +-validate:["streamname_with_wildcard_and_variables"],label:"Fallback stream",pointer:{main:h,index:"defaultStream"},help:"When this is set, if someone attempts to view a stream that does not exist, or is offline, they will be redirected to this stream instead. $stream may be used to refer to the original stream name.",LTSonly:!0},{type:"checkbox",label:"Force configurations save",pointer:{main:h,index:"save"},help:"Tick the box in order to force an immediate save to the config.json MistServer uses to save your settings. Saving will otherwise happen upon closing MistServer. Don't forget to press save after ticking the box."}, +-{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){var a={config:h},b={};b.limit=g.limit?i.val()*g.limit:0;b.exceptions=g.exceptions;if(b.exceptions===null)b.exceptions=[];a.bandwidth=b;if(h.save)a.save=h.save;delete h.save;mist.send(function(){UI.navto("Overview")},a)}}]}]));if(mist.data.LTS){var Q=function(a){function b(a){if(a.update){var d="";"progress"in a.update&&(d=" ("+a.update.progress+"%)");e.text("Updating.."+d);c(a.log);setTimeout(function(){mist.send(function(a){b(a)}, +-{update:true})},1E3)}else UI.showTab("Overview")}function c(a){a=a.filter(function(a){return a[1]=="UPDR"});if(a.length){var b=$("<div>");e.append(b);for(var d in a)b.append($("<div>").text(a[d][2]))}}if(!a.update||!("uptodate"in a.update)){e.text("Unknown, checking..");setTimeout(function(){mist.send(function(a){"update"in a&&Q(a)},{checkupdate:true})},5E3)}else if(a.update.error)e.addClass("red").text(a.update.error);else if(a.update.uptodate)e.text("Your version is up to date.").addClass("green"); +-else{if(a.update.progress){e.addClass("orange").removeClass("red").text("Updating..");b(a)}else{e.text("");e.append($("<span>").addClass("red").text("On "+(new Date(a.update.date)).toLocaleDateString()+" version "+a.update.version+" became available."));(!a.update.url||a.update.url.slice(-4)!=".zip")&&e.append($("<button>").text("Rolling update").css({"font-size":"1em","margin-left":"1em"}).click(function(){if(confirm("Are you sure you want to execute a rolling update?")){e.addClass("orange").removeClass("red").text("Rolling update command sent.."); +-mist.send(function(a){b(a)},{autoupdate:true})}}));var d=$("<a>").attr("href",a.update.url).attr("target","_blank").text("Manual download");d[0].protocol="https:";e.append($("<div>").append(d))}c(a.log)}};Q(mist.data);if("license"in mist.data.config){if("active_products"in mist.data.config.license&&Object.keys(mist.data.config.license.active_products).length){var F=$("<table>").css("text-indent","0");o.html(F);F.append($("<tr>").append($("<th>").append("Product")).append($("<th>").append("Updates until")).append($("<th>").append("Use until")).append($("<th>").append("Max. simul. instances"))); +-for(var r in mist.data.config.license.active_products){var J=mist.data.config.license.active_products[r];F.append($("<tr>").append($("<td>").append(J.name)).append($("<td>").append(J.updates_final?J.updates_final:"∞")).append($("<td>").append(J.use_final?J.use_final:"∞")).append($("<td>").append(J.amount?J.amount:"∞")))}}else o.text("None. ");o.append($("<a>").text("More details").attr("href","https://shop.mistserver.org/myinvoices").attr("target","_blank"))}}else e.text("");var za= +-function(){var a={totals:{fields:["clients"],start:-10},active_streams:true};if(!("cabailities"in mist.data))a.capabilities=true;mist.send(function(){Aa()},a)},Aa=function(){l.text("active_streams"in mist.data?mist.data.active_streams?mist.data.active_streams.length:0:"?");if("totals"in mist.data&&"all_streams"in mist.data.totals)var a=mist.data.totals.all_streams.all_protocols.clients,a=a.length?UI.format.number(a[a.length-1][1]):0;else a="Loading..";f.text(a);t.text(UI.format.dateTime(mist.data.config.time, +-"long"));m.html("");a=0;"license"in mist.data.config&&"user_msg"in mist.data.config.license&&mist.data.log.unshift([mist.data.config.license.time,"ERROR",mist.data.config.license.user_msg]);for(var b in mist.data.log){var c=mist.data.log[b];if(["FAIL","ERROR"].indexOf(c[1])>-1){a++;var d=$("<span>").addClass("content").addClass("red"),e=c[2].split("|");for(b in e)d.append($("<span>").text(e[b]));m.append($("<div>").append($("<span>").append(UI.format.time(c[0]))).append(d));if(a==5)break}}a==0&&m.html("None."); +-a=[];c=[];for(b in mist.data.config.protocols){d=mist.data.config.protocols[b];a.indexOf(d.connector)>-1||a.push(d.connector)}k.text(a.length?a.join(", "):"None.");if("capabilities"in mist.data){for(b in mist.data.capabilities.connectors)a.indexOf(b)==-1&&c.push(b);w.text(c.length?c.join(", "):"None.")}else w.text("Loading..")};za();Aa();UI.interval.set(za,3E4);break;case "Protocols":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});c.append("Loading.."); +-return}var C=$("<tbody>");c.append(UI.buildUI([{type:"help",help:"You can find an overview of all the protocols and their relevant information here. You can add, edit or delete protocols."}])).append($("<button>").text("Delete all protocols").click(function(){if(confirm("Are you sure you want to delete all currently configured protocols?")){mist.data.config.protocols=[];mist.send(function(){UI.navto("Protocols")},{config:mist.data.config})}})).append($("<button>").text("Enable default protocols").click(function(){var a= +-Object.keys(mist.data.capabilities.connectors),b;for(b in mist.data.config.protocols){var c=a.indexOf(mist.data.config.protocols[b].connector);c>-1&&a.splice(c,1)}var d=[];for(b in a)(!("required"in mist.data.capabilities.connectors[a[b]])||Object.keys(mist.data.capabilities.connectors[a[b]].required).length==0)&&d.push(a[b]);c="Click OK to enable disabled protocols with their default settings:\n ";c=d.length?c+d.join(", "):c+"None.";if(d.length!=a.length){a=a.filter(function(a){return d.indexOf(a)< +-0});c=c+("\n\nThe following protocols can only be set manually:\n "+a.join(", "))}if(confirm(c)&&d.length){if(mist.data.config.protocols===null)mist.data.config.protocols=[];for(b in d)mist.data.config.protocols.push({connector:d[b]});mist.send(function(){UI.navto("Protocols")},{config:mist.data.config})}})).append("<br>").append($("<button>").text("New protocol").click(function(){UI.navto("Edit Protocol")}).css("clear","both")).append($("<table>").html($("<thead>").html($("<tr>").html($("<th>").text("Protocol")).append($("<th>").text("Status")).append($("<th>").text("Settings")).append($("<th>")))).append(C)); +-var Ba=function(){function a(b){var c=mist.data.capabilities.connectors[b.connector];if(!c)return"";var d=[],e=["required","optional"],M;for(M in e)for(var g in c[e[M]])b[g]&&b[g]!=""?d.push(g+": "+b[g]):c[e[M]][g]["default"]&&d.push(g+": "+c[e[M]][g]["default"]);return $("<span>").addClass("description").text(d.join(", "))}C.html("");for(var b in mist.data.config.protocols){var c=mist.data.config.protocols[b],d=mist.data.capabilities.connectors[c.connector];C.append($("<tr>").data("index",b).append($("<td>").text(d&& +-d.friendly?d.friendly:c.connector)).append($("<td>").html(UI.format.status(c))).append($("<td>").html(a(c))).append($("<td>").css("text-align","right").html($("<button>").text("Edit").click(function(){UI.navto("Edit Protocol",$(this).closest("tr").data("index"))})).append($("<button>").text("Delete").click(function(){var a=$(this).closest("tr").data("index");if(confirm('Are you sure you want to delete the protocol "'+mist.data.config.protocols[a].connector+'"?')){mist.send(function(){UI.navto("Protocols")}, +-{deleteprotocol:mist.data.config.protocols[a]});mist.data.config.protocols.splice(a,1)}}))))}};Ba();UI.interval.set(function(){mist.send(function(){Ba()})},1E4);break;case "Edit Protocol":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a,b)},{capabilities:!0});c.append("Loading..");return}var K=!1;""!=b&&0<=b&&(K=!0);var U={};for(r in mist.data.config.protocols)U[mist.data.config.protocols[r].connector]=1;var Ca=function(a){var b=mist.data.capabilities.connectors[a],c= +-mist.convertBuildOptions(b,p);if(K)var d=$.extend({},p);c.push({type:"hidden",pointer:{main:p,index:"connector"},value:a});c.push({type:"buttons",buttons:[{type:"save",label:"Save","function":function(){var a={};K?a.updateprotocol=[d,p]:a.addprotocol=p;mist.send(function(){UI.navto("Protocols")},a)}},{type:"cancel",label:"Cancel","function":function(){UI.navto("Protocols")}}]});if("deps"in b&&b.deps!=""){F=$("<span>").text("Dependencies:");$ul=$("<ul>");F.append($ul);if(typeof b.deps=="string")b.deps= +-b.deps.split(", ");for(var e in b.deps){a=$("<li>").text(b.deps[e]+" ");$ul.append(a);typeof U[b.deps[e]]!="undefined"||typeof U[b.deps[e]+".exe"]!="undefined"?a.append($("<span>").addClass("green").text("(Configured)")):a.append($("<span>").addClass("red").text("(Not yet configured)"))}c.unshift({type:"text",text:F[0].innerHTML})}return UI.buildUI(c)},U={};for(r in mist.data.config.protocols)U[mist.data.config.protocols[r].connector]=1;if(K){var s=mist.data.config.protocols[b],p=s;c.find("h2").append(' "'+ +-s.connector+'"');c.append(Ca(s.connector))}else{c.html($("<h2>").text("New Protocol"));var p={},u=[["",""]];for(r in mist.data.capabilities.connectors)u.push([r,mist.data.capabilities.connectors[r].friendly?mist.data.capabilities.connectors[r].friendly:r]);var R=$("<span>");c.append(UI.buildUI([{label:"Protocol",type:"select",select:u,"function":function(){$(this).getval()!=""&&R.html(Ca($(this).getval()))}}])).append(R)}break;case "Streams":if(!("capabilities"in mist.data)){c.html("Loading..");mist.send(function(){UI.navto(a)}, +-{capabilities:!0});return}var Da=$("<button>"),L=$("<span>").text("Loading..");c.append(UI.buildUI([{type:"help",help:"Here you can create, edit or delete new and existing streams. Go to stream preview or embed a video player on your website."},$("<div>").css({width:"45.25em",display:"flex","justify-content":"flex-end"}).append(Da).append($("<button>").text("Create a new stream").click(function(){UI.navto("Edit")}))])).append(L);""==b&&(h=mist.stored.get(),"viewmode"in h&&(b=h.viewmode));Da.text("Switch to "+ +-("thumbnails"==b?"list":"thumbnail")+" view").click(function(){mist.stored.set("viewmode",b=="thumbnails"?"list":"thumbnails");UI.navto("Streams",b=="thumbnails"?"list":"thumbnails")});var A=$.extend(!0,{},mist.data.streams),ka=function(a,b){var c=$.extend({},b);delete c.meta;delete c.error;c.online=2;c.name=a;c.ischild=true;return c},la=function(b,d,e){L.remove();switch(b){case "thumbnails":var g=$("<div>").addClass("preview_icons"),f;f=e||[];d.sort();d.unshift("");L.remove();c.append($("<h2>").text(a)).append(UI.buildUI([{label:"Filter the streams", +-type:"datalist",datalist:d,pointer:{main:{},index:"stream"},help:"If you type something here, the box below will only show streams with names that contain your text.","function":function(){var a=$(this).val();g.children().each(function(){$(this).hide();$(this).attr("data-stream").indexOf(a)>-1&&$(this).show()})}}]));d.shift();c.append($("<span>").addClass("description").text("Choose a stream below.")).append(g);for(var i in d){var b=d[i],h="",j=$("<button>").text("Delete").click(function(){var a= +-$(this).closest("div").attr("data-stream");if(confirm('Are you sure you want to delete the stream "'+a+'"?')){delete mist.data.streams[a];var b={};b.deletestream=[a];mist.send(function(){UI.navto("Streams")},b)}}),k=$("<button>").text("Settings").click(function(){UI.navto("Edit",$(this).closest("div").attr("data-stream"))}),e=$("<button>").text("Preview").click(function(){UI.navto("Preview",$(this).closest("div").attr("data-stream"))}),l=$("<button>").text("Embed").click(function(){UI.navto("Embed", +-$(this).closest("div").attr("data-stream"))}),q=$("<span>").addClass("image");if(b.indexOf("+")>-1){h=b.split("+");h=mist.data.streams[h[0]].source+h[1];k=j="";q.addClass("wildcard")}else{h=mist.data.streams[b].source;if(f.indexOf(b)>-1){l=e="";q.addClass("folder")}}g.append($("<div>").append($("<span>").addClass("streamname").text(b)).append(q).append($("<span>").addClass("description").text(h)).append($("<span>").addClass("button_container").append(k).append(j).append(e).append(l)).attr("title", +-b).attr("data-stream",b))}break;default:var m=$("<tbody>").append($("<tr>").append("<td>").attr("colspan",6).text("Loading.."));i=$("<table>").html($("<thead>").html($("<tr>").html($("<th>").text("Stream name").attr("data-sort-type","string").addClass("sorting-asc")).append($("<th>").text("Source").attr("data-sort-type","string")).append($("<th>").text("Status").attr("data-sort-type","int")).append($("<th>").css("text-align","right").text("Connections").attr("data-sort-type","int")).append($("<th>")).append($("<th>")))).append(m); +-c.append(i);i.stupidtable();var n=function(){var a=[],b;for(b in mist.data.active_streams)a.push({streams:[mist.data.active_streams[b]],fields:["clients"],start:-2});mist.send(function(){$.extend(true,A,mist.data.streams);var a=0;m.html("");d.sort();for(var b in d){var c=d[b],e;e=c in mist.data.streams?mist.data.streams[c]:A[c];var g=$("<td>").css("text-align","right").html($("<span>").addClass("description").text("Loading..")),f=0;if(typeof mist.data.totals!="undefined"&&typeof mist.data.totals[c]!= +-"undefined"){var i=mist.data.totals[c].all_protocols.clients,f=0;if(i.length){for(a in i)f=f+i[a][1];f=Math.round(f/i.length)}}g.html(UI.format.number(f));if(f==0&&e.online==1)e.online=2;f=$("<td>").css("text-align","right").css("white-space","nowrap");(!("ischild"in e)||!e.ischild)&&f.html($("<button>").text("Settings").click(function(){UI.navto("Edit",$(this).closest("tr").data("index"))})).append($("<button>").text("Delete").click(function(){var a=$(this).closest("tr").data("index");if(confirm('Are you sure you want to delete the stream "'+ +-a+'"?')){delete mist.data.streams[a];var b={};mist.data.LTS?b.deletestream=[a]:b.streams=mist.data.streams;mist.send(function(){UI.navto("Streams")},b)}}));i=$("<span>").text(e.name);e.ischild&&i.css("padding-left","1em");var h=UI.format.status(e),M=$("<button>").text("Preview").click(function(){UI.navto("Preview",$(this).closest("tr").data("index"))}),q=$("<button>").text("Embed").click(function(){UI.navto("Embed",$(this).closest("tr").data("index"))});if("filesfound"in A[c]||e.online<0){h.html(""); +-M="";g.html("");q=""}m.append($("<tr>").data("index",c).html($("<td>").html(i).attr("title",e.name=="..."?"The results were truncated":e.name).addClass("overflow_ellipsis")).append($("<td>").text(e.source).attr("title",e.source).addClass("description").addClass("overflow_ellipsis").css("max-width","20em")).append($("<td>").data("sort-value",e.online).html(h)).append(g).append($("<td>").css("white-space","nowrap").html(M).append(q)).append(f));a++}},{totals:a,active_streams:true})};if(mist.data.LTS){var o= +-0,p=0;for(f in mist.data.streams){i=mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"];if(!i)break;if(mist.inputMatch(i.source_match,mist.data.streams[f].source)){A[f].source=A[f].source+"*";A[f].filesfound=null;mist.send(function(a,b){var c=b.stream,d=0,e;a:for(e in a.browse.files){var f;for(f in mist.data.capabilities.inputs)if(!(f.indexOf("Buffer")>=0||f.indexOf("Buffer.exe")>=0||f.indexOf("Folder")>=0||f.indexOf("Folder.exe")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[f].source_match, +-"/"+a.browse.files[e])){var g=c+"+"+a.browse.files[e];A[g]=ka(g,mist.data.streams[c]);A[g].source=mist.data.streams[c].source+a.browse.files[e];d++;if(d>=500){A[c+"+zzzzzzzzz"]={ischild:true,name:"...",online:-1};break a}}}"files"in a.browse&&a.browse.files.length?A[c].filesfound=true:mist.data.streams[c].filesfound=false;p++;if(o==p){mist.send(function(){n()},{active_streams:true});UI.interval.set(function(){n()},5E3)}},{browse:mist.data.streams[f].source},{stream:f});o++}}if(o==0){mist.send(function(){n()}, +-{active_streams:true});UI.interval.set(function(){n()},5E3)}}else{mist.send(function(){n()},{active_streams:true});UI.interval.set(function(){n()},5E3)}}};if(mist.data.LTS){var ma=0,Ea=0,u={},Fa=[];for(h in mist.data.streams)if(mist.inputMatch((mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"]).source_match,mist.data.streams[h].source))Fa.push(h),mist.send(function(a,c){var d=c.stream,e=0,f;a:for(f in a.browse.files){var g;for(g in mist.data.capabilities.inputs)if(!(g.indexOf("Buffer")>= +-0||g.indexOf("Folder")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[g].source_match,"/"+a.browse.files[f])){u[d+"+"+a.browse.files[f]]=true;e++;if(e>=500){u[d+"+zzzzzzzzz"]=true;break a}}}Ea++;ma==Ea&&mist.send(function(){for(var a in mist.data.active_streams){var c=mist.data.active_streams[a].split("+");if(c.length>1&&c[0]in mist.data.streams){u[mist.data.active_streams[a]]=true;A[mist.data.active_streams[a]]=ka(mist.data.active_streams[a],mist.data.streams[c[0]])}}u=Object.keys(u);u=u.concat(Object.keys(mist.data.streams)); +-u.sort();la(b,u,Fa)},{active_streams:true})},{browse:mist.data.streams[h].source},{stream:h}),ma++;0==ma&&mist.send(function(){for(var a in mist.data.active_streams){var c=mist.data.active_streams[a].split("+");if(c.length>1&&c[0]in mist.data.streams){u[mist.data.active_streams[a]]=true;A[mist.data.active_streams[a]]=ka(mist.data.active_streams[a],mist.data.streams[c[0]])}}u=Object.keys(u);mist.data.streams&&(u=u.concat(Object.keys(mist.data.streams)));u.sort();la(b,u)},{active_streams:!0})}else la(b, +-Object.keys(mist.data.streams));break;case "Edit":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a,b)},{capabilities:!0});c.append("Loading..");return}K=!1;""!=b&&(K=!0);if(K){var Ga=b,p=mist.data.streams[Ga];c.find("h2").append(' "'+Ga+'"')}else c.html($("<h2>").text("New Stream")),p={};var Ha=[];for(r in mist.data.capabilities.inputs)Ha.push(mist.data.capabilities.inputs[r].source_match);var da=$("<div>"),Ia=function(a){var c={};if(!mist.data.streams)mist.data.streams= +-{};mist.data.streams[p.name]=p;b!=p.name&&delete mist.data.streams[b];c.addstream={};c.addstream[p.name]=p;if(b!=p.name)c.deletestream=[b];if(p.stop_sessions&&b!=""){c.stop_sessions=b;delete p.stop_sessions}mist.send(function(){delete mist.data.streams[p.name].online;delete mist.data.streams[p.name].error;UI.navto(a,a=="Preview"?p.name:"")},c)},Ja=$("<style>").text("button.saveandpreview { display: none; }"),N=$("<span>"),na=function(){var a=c.find("[name=name]").val();if(a){var b=parseURL(mist.user.host), +-d=c.find("[name=source]").val(),e=d.match(/@.*/);e&&(e=e[0].substring(1));var f=d.replace(/(?:.+?):\/\//,""),f=f.split("/"),f=f[0],f=f.split(":"),f=f[0];(d=d.match(/:\d+/))&&(d=d[0]);var g={},i=["RTMP","RTSP","RTMP.exe","RTSP.exe"],h;for(h in i)i[h]in mist.data.capabilities.connectors&&(g[i[h]]=mist.data.capabilities.connectors[i[h]].optional.port["default"]);var i={RTMP:1935,"RTMP.exe":1935,RTSP:554,"RTSP.exe":554,TS:-1,"TS.exe":-1},j;for(j in g){for(h in mist.data.config.protocols){var k=mist.data.config.protocols[h]; +-if(k.connector==j){if("port"in k)g[j]=k.port;break}}g[j]=g[j]==i[j]?"":":"+g[j]}g.TS="";g["TS.exe"]="";N.find(".field").closest("label").hide();for(h in g){var q;j=d?d:g[h];switch(h){case "RTMP":case "RTMP.exe":q="rtmp://"+b.host+j+"/"+(e?e:"live")+"/";N.find(".field.RTMPurl").setval(q).closest("label").show();N.find(".field.RTMPkey").setval(a==""?"STREAMNAME":a).closest("label").show();q=q+(a==""?"STREAMNAME":a);break;case "RTSP":case "RTSP.exe":q="rtsp://"+b.host+j+"/"+(a==""?"STREAMNAME":a)+(e? +-"?pass="+e:"");break;case "TS":case "TS.exe":q="udp://"+(f==""?b.host:f)+j+"/"}N.find(".field."+h.replace(".exe","")).setval(q).closest("label").show()}}},Ka=$("<div>"),oa={},u=[],La=$("<div>");for(r in mist.data.capabilities.processes)u.push([r,mist.data.capabilities.processes[r].hrn?mist.data.capabilities.processes[r].hrn:mist.data.capabilities.processes[r].name]);if(u.length){var ab=[{label:"New process",type:"select",select:u,value:u[0][0],pointer:{main:oa,index:"process"},"function":function(){var a= +-$(this).getval();if(a!=null){var a=mist.data.capabilities.processes[a],b=[$("<h4>").text(a.name+" Process options")];La.html(UI.buildUI(b.concat(mist.convertBuildOptions(a,oa))))}}},La];Ka.append(UI.buildUI([$("<br>"),$("<h3>").text("Stream processes"),{label:"Stream processes",itemLabel:"stream process",type:"sublist",sublist:ab,saveas:oa,pointer:{main:p,index:"processes"}}]))}c.append(UI.buildUI([{label:"Stream name",type:"str",validate:["required","streamname"],pointer:{main:p,index:"name"},help:"Set the name this stream will be recognised by for players and/or stream pushing."}, +-{label:"Source",type:"browse",filetypes:Ha,pointer:{main:p,index:"source"},help:"<p> Below is the explanation of the input methods for MistServer. Anything between brackets () will go to default settings if not specified. </p> <table class=valigntop> <tr> <th colspan=3><b>File inputs</b></th> </tr> <tr> <th>File</th> <td> Linux/MacOS: /PATH/FILE<br> Windows: /cygdrive/DRIVE/PATH/FILE </td> <td> For file input please specify the proper path and file.<br> Supported inputs are: DTSC, FLV, MP3. MistServer Pro has TS, MP4, ISMV added as input. </td> </tr> <th> Folder </th> <td> Linux/MacOS: /PATH/<br> Windows: /cygdrive/DRIVE/PATH/ </td> <td class=LTSonly> A folder stream makes all the recognised files in the selected folder available as a stream. </td> </tr> <tr><td colspan=3> </td></tr> <tr> <th colspan=3><b>Push inputs</b></th> </tr> <tr> <th>RTMP</th> <td>push://(IP)(@PASSWORD)</td> <td> IP is white listed IP for pushing towards MistServer, if left empty all are white listed.<br> PASSWORD is the application under which to push to MistServer, if it doesn't match the stream will be rejected. PASSWORD is MistServer Pro only. </td> </tr> <tr> <th>RTSP</th> <td>push://(IP)(@PASSWORD)</td> <td class=LTSonly>IP is white listed IP for pushing towards MistServer, if left empty all are white listed.</td> </tr> <tr> <th>TS</th> <td>tsudp://(IP):PORT(/INTERFACE)</td> <td class=LTSonly> IP is the IP address used to listen for this stream, multi-cast IP range is: 224.0.0.0 - 239.255.255.255. If IP is not set all addresses will listened to.<br> PORT is the port you reserve for this stream on the chosen IP.<br> INTERFACE is the interface used, if left all interfaces will be used. </td> </tr> <tr><td colspan=3> </td></tr> <tr> <th colspan=3><b>Pull inputs</b></th> </tr> <tr> <th>DTSC</th> <td>dtsc://MISTSERVER_IP:PORT/(STREAMNAME)</td> <td>MISTSERVER_IP is the IP of another MistServer to pull from.<br> PORT is the DTSC port of the other MistServer. (default is 4200)<br> STREAMNAME is the name of the target stream on the other MistServer. If left empty, the name of this stream will be used. </td> </tr> <tr> <th>HLS</th> <td>http://URL/TO/STREAM.m3u8</td> <td class=LTSonly>The URL where the HLS stream is available to MistServer.</td> </tr> <tr> <th>RTSP</th> <td>rtsp://(USER:PASSWORD@)IP(:PORT)(/path)</td> <td class=LTSonly> USER:PASSWORD is the account used if authorization is required.<br> IP is the IP address used to pull this stream from.<br> PORT is the port used to connect through.<br> PATH is the path to be used to identify the correct stream. </td> </tr> </table>".replace(/LTSonly/g, +-mist.data.LTS?'""':"LTSonly"),"function":function(){var a=$(this).val();Ja.remove();N.html("");if(a!=""){var b=null,d;for(d in mist.data.capabilities.inputs)if(typeof mist.data.capabilities.inputs[d].source_match!="undefined"&&mist.inputMatch(mist.data.capabilities.inputs[d].source_match,a)){b=d;break}if(b===null)da.html($("<h3>").text("Unrecognized input").addClass("red")).append($("<span>").text("Please edit the stream source.").addClass("red"));else{b=mist.data.capabilities.inputs[b];da.html($("<h3>").text(b.name+ +-" Input options"));var e=mist.convertBuildOptions(b,p);"always_match"in mist.data.capabilities.inputs[d]&&mist.inputMatch(mist.data.capabilities.inputs[d].always_match,a)&&e.push({label:"Always on",type:"checkbox",help:"Keep this input available at all times, even when there are no active viewers.",pointer:{main:p,index:"always_on"}});da.append(UI.buildUI(e));if(b.name=="Folder")c.append(Ja);else if(["Buffer","Buffer.exe","TS","TS.exe"].indexOf(b.name)>-1){d=[$("<br>"),$("<span>").text("Configure your source to push to:")]; ++$("<span>").text("Loading.."),l=$("<span>"),n=$("<span>").addClass("logs"),h=$("<span>"),t=$("<span>"),m=$("<span>").text("Unknown"),k=$("<span>"),w=$("<span>"),i=parseURL(mist.user.host),i=i.protocol+i.host+i.port,g={};c.append(UI.buildUI([{type:"help",help:"You can find most basic information about your MistServer here.<br>You can also set the debug level and force a save to the config.json file that MistServer uses to save your settings. "},{type:"span",label:"Version",pointer:{main:mist.data.config, ++index:"version"}},{type:"span",label:"Version check",value:e},{type:"span",label:"Server time",value:t},{type:"span",label:"Licensed to",value:"license"in mist.data.config?mist.data.config.license.user:""},{type:"span",label:"Active licenses",value:m},{type:"span",label:"Configured streams",value:mist.data.streams?Object.keys(mist.data.streams).length:0},{type:"span",label:"Active streams",value:l},{type:"span",label:"Current connections",value:h},{type:"span",label:"Enabled protocols",value:k},{type:"span", ++label:"Disabled protocols",value:w},{type:"span",label:"Recent problems",value:n},$("<br>"),$("<h3>").text("Write config now"),{type:"help",help:"Tick the box in order to force an immediate save to the config.json MistServer uses to save your settings. Saving will otherwise happen upon closing MistServer. Don't forget to press save after ticking the box."},{type:"checkbox",label:"Force configurations save",pointer:{main:g,index:"save"}},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){var a= ++{};if(g.save)a.save=g.save;delete g.save;mist.send(function(){UI.navto("Overview")},a)}}]}]));if(mist.data.LTS){var f=function(a){function b(a){if(a.update){var d="";"progress"in a.update&&(d=" ("+a.update.progress+"%)");e.text("Updating.."+d);c(a.log);setTimeout(function(){mist.send(function(a){b(a)},{update:true})},1E3)}else UI.showTab("Overview")}function c(a){a=a.filter(function(a){return a[1]=="UPDR"});if(a.length){var b=$("<div>");e.append(b);for(var d in a)b.append($("<div>").text(a[d][2]))}} ++if(!a.update||!("uptodate"in a.update)){e.text("Unknown, checking..");setTimeout(function(){mist.send(function(a){"update"in a&&f(a)},{checkupdate:true})},5E3)}else if(a.update.error)e.addClass("red").text(a.update.error);else if(a.update.uptodate)e.text("Your version is up to date.").addClass("green");else{if(a.update.progress){e.addClass("orange").removeClass("red").text("Updating..");b(a)}else{e.text("");e.append($("<span>").addClass("red").text("On "+(new Date(a.update.date)).toLocaleDateString()+ ++" version "+a.update.version+" became available."));(!a.update.url||a.update.url.slice(-4)!=".zip")&&e.append($("<button>").text("Rolling update").css({"font-size":"1em","margin-left":"1em"}).click(function(){if(confirm("Are you sure you want to execute a rolling update?")){e.addClass("orange").removeClass("red").text("Rolling update command sent..");mist.send(function(a){b(a)},{autoupdate:true})}}));var d=$("<a>").attr("href",a.update.url).attr("target","_blank").text("Manual download");d[0].protocol= ++"https:";e.append($("<div>").append(d))}c(a.log)}};f(mist.data);if("license"in mist.data.config){if("active_products"in mist.data.config.license&&Object.keys(mist.data.config.license.active_products).length){var j=$("<table>").css("text-indent","0");m.html(j);j.append($("<tr>").append($("<th>").append("Product")).append($("<th>").append("Updates until")).append($("<th>").append("Use until")).append($("<th>").append("Max. simul. instances")));for(var r in mist.data.config.license.active_products){var F= ++mist.data.config.license.active_products[r];j.append($("<tr>").append($("<td>").append(F.name)).append($("<td>").append(F.updates_final?F.updates_final:"∞")).append($("<td>").append(F.use_final?F.use_final:"∞")).append($("<td>").append(F.amount?F.amount:"∞")))}}else m.text("None. ");m.append($("<a>").text("More details").attr("href","https://shop.mistserver.org/myinvoices").attr("target","_blank"))}}else e.text("");var ya=function(){var a={totals:{fields:["clients"],start:-10},active_streams:true}; ++if(!("cabailities"in mist.data))a.capabilities=true;mist.send(function(){za()},a)},za=function(){l.text("active_streams"in mist.data?mist.data.active_streams?mist.data.active_streams.length:0:"?");if("totals"in mist.data&&"all_streams"in mist.data.totals)var a=mist.data.totals.all_streams.all_protocols.clients,a=a.length?UI.format.number(a[a.length-1][1]):0;else a="Loading..";h.text(a);t.text(UI.format.dateTime(mist.data.config.time,"long"));n.html("");a=0;"license"in mist.data.config&&"user_msg"in ++mist.data.config.license&&mist.data.log.unshift([mist.data.config.license.time,"ERROR",mist.data.config.license.user_msg]);for(var b in mist.data.log){var c=mist.data.log[b];if(["FAIL","ERROR"].indexOf(c[1])>-1){a++;var d=$("<span>").addClass("content").addClass("red"),e=c[2].split("|");for(b in e)d.append($("<span>").text(e[b]));n.append($("<div>").append($("<span>").append(UI.format.time(c[0]))).append(d));if(a==5)break}}a==0&&n.html("None.");a=[];c=[];for(b in mist.data.config.protocols){d=mist.data.config.protocols[b]; ++a.indexOf(d.connector)>-1||a.push(d.connector)}k.text(a.length?a.join(", "):"None.");if("capabilities"in mist.data){for(b in mist.data.capabilities.connectors)a.indexOf(b)==-1&&c.push(b);w.text(c.length?c.join(", "):"None.")}else w.text("Loading..")};ya();za();UI.interval.set(ya,3E4);break;case "General":var g={serverid:mist.data.config.serverid,debug:mist.data.config.debug,accesslog:mist.data.config.accesslog,prometheus:mist.data.config.prometheus,sessionViewerMode:mist.data.config.sessionViewerMode, ++sessionInputMode:mist.data.config.sessionInputMode,sessionOutputMode:mist.data.config.sessionOutputMode,sessionUnspecifiedMode:mist.data.config.sessionUnspecifiedMode,tknMode:mist.data.config.tknMode,sessionStreamInfoMode:mist.data.config.sessionStreamInfoMode,defaultStream:mist.data.config.defaultStream,trustedproxy:mist.data.config.trustedproxy,location:"location"in mist.data.config?mist.data.config.location:{}},C={};"bandwidth"in mist.data&&(C=mist.data.bandwidth,null==C&&(C={}),C.limit||(C.limit= ++""));var Aa=$("<select>").html($("<option>").val(1).text("bytes/s")).append($("<option>").val(1024).text("KiB/s")).append($("<option>").val(1048576).text("MiB/s")).append($("<option>").val(1073741824).text("GiB/s"));c.html(UI.buildUI([$("<h2>").text("General settings"),{type:"help",help:"These are settings that apply to your MistServer instance in general."},{type:"str",label:"Human readable name",pointer:{main:g,index:"serverid"},help:"You can name your MistServer here for personal use. You'll still need to set host name within your network yourself."}, ++{type:"debug",label:"Debug level",pointer:{main:g,index:"debug"},help:"You can set the amount of debug information MistServer saves in the log. A full reboot of MistServer is required before some components of MistServer can post debug information."},{type:"selectinput",label:"Access log",selectinput:[["","Do not track"],["LOG","Log to MistServer log"],[{type:"str",label:"Path"},"Log to file"]],pointer:{main:g,index:"accesslog"},help:"Enable access logs."},{type:"selectinput",label:"Prometheus stats output", ++selectinput:[["","Disabled"],[{type:"str",label:"Passphrase"},"Enabled"]],pointer:{main:g,index:"prometheus"},help:"Make stats available in Prometheus format. These can be accessed via "+i+"/PASSPHRASE or "+i+"/PASSPHRASE.json."},{type:"inputlist",label:"Trusted proxies",help:"List of proxy server addresses that are allowed to override the viewer IP address to arbitrary values.<br>You may use a hostname or IP address.",pointer:{main:g,index:"trustedproxy"}},{type:"str",validate:["streamname_with_wildcard_and_variables"], ++label:"Fallback stream",pointer:{main:g,index:"defaultStream"},help:"When this is set, if someone attempts to view a stream that does not exist, or is offline, they will be redirected to this stream instead. $stream may be used to refer to the original stream name."},$("<h3>").text("Sessions"),{type:"bitmask",label:"Bundle viewer sessions by",bitmask:[[8,"Stream name"],[4,"IP address"],[2,"Token"],[1,"Protocol"]],pointer:{main:g,index:"sessionViewerMode"},help:"Change the way viewer connections are bundled into sessions.<br>Default: stream name, viewer IP and token"}, ++{type:"bitmask",label:"Bundle input sessions by",bitmask:[[8,"Stream name"],[4,"IP address"],[2,"Token"],[1,"Protocol"]],pointer:{main:g,index:"sessionInputMode"},help:"Change the way input connections are bundled into sessions.<br>Default: stream name, input IP, token and protocol"},{type:"bitmask",label:"Bundle output sessions by",bitmask:[[8,"Stream name"],[4,"IP address"],[2,"Token"],[1,"Protocol"]],pointer:{main:g,index:"sessionOutputMode"},help:"Change the way output connections are bundled into sessions.<br>Default: stream name, output IP, token and protocol"}, ++{type:"bitmask",label:"Bundle unspecified sessions by",bitmask:[[8,"Stream name"],[4,"IP address"],[2,"Token"],[1,"Protocol"]],pointer:{main:g,index:"sessionUnspecifiedMode"},help:"Change the way unspecified connections are bundled into sessions.<br>Default: none"},{type:"select",label:"Treat HTTP-only sessions as",select:[[1,"A viewer session"],[2,"An output session: skip executing the USER_NEW and USER_END triggers"],[4,"A separate 'unspecified' session: skip executing the USER_NEW and USER_END triggers"], ++[3,"Do not start a session: skip executing the USER_NEW and USER_END triggers and do not count for statistics"]],pointer:{main:g,index:"sessionStreamInfoMode"},help:"Change the way the stream info connection gets treated.<br>Default: as a viewer session"},{type:"bitmask",label:"Communicate session token",bitmask:[[8,"Write to cookie"],[4,"Write to URL parameter"],[2,"Read from cookie"],[1,"Read from URL parameter"]],pointer:{main:g,index:"tknMode"},help:"Change the way the session token gets passed to and from MistServer, which can be set as a cookie or URL parameter named `tkn`. Reading the session token as a URL parameter takes precedence over reading from the cookie.<br>Default: all"}, ++$("<h3>").text("Load balancer"),{type:"help",help:"If you're using MistServer's load balancer, the information below is passed to it so that it can make informed decisions."},{type:"selectinput",label:"Server's bandwidth limit",selectinput:[["","Default (1 gbps)"],[{label:"Custom",type:"int",min:0,unit:Aa},"Custom"]],pointer:{main:C,index:"limit"},help:"This is the amount of traffic this server is willing to handle."},{type:"inputlist",label:"Bandwidth exceptions",pointer:{main:C,index:"exceptions"}, ++help:"Data sent to the hosts and subnets listed here will not count towards reported bandwidth usage.<br>Examples:<ul><li>192.168.0.0/16</li><li>localhost</li><li>10.0.0.0/8</li><li>fe80::/16</li></ul>"},{type:"int",step:1E-8,label:"Server latitude",pointer:{main:g.location,index:"lat"},help:"This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them."},{type:"int",step:1E-8,label:"Server longitude",pointer:{main:g.location, ++index:"lon"},help:"This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them."},{type:"str",label:"Server location name",pointer:{main:g.location,index:"name"},help:"This setting is only useful when MistServer is combined with a load balancer. This will be displayed as the server's location."},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(a){$(a).text("Saving..");var a={config:g},b= ++{};b.limit=C.limit?Aa.val()*C.limit:0;b.exceptions=C.exceptions;if(b.exceptions===null)b.exceptions=[];a.bandwidth=b;mist.send(function(){UI.navto("Overview")},a)}}]}]));break;case "Protocols":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});c.append("Loading..");return}var D=$("<tbody>");c.append(UI.buildUI([{type:"help",help:"You can find an overview of all the protocols and their relevant information here. You can add, edit or delete protocols."}])).append($("<button>").text("Delete all protocols").click(function(){if(confirm("Are you sure you want to delete all currently configured protocols?")){mist.data.config.protocols= ++[];mist.send(function(){UI.navto("Protocols")},{config:mist.data.config})}})).append($("<button>").text("Enable default protocols").click(function(){var a=Object.keys(mist.data.capabilities.connectors),b;for(b in mist.data.config.protocols){var c=a.indexOf(mist.data.config.protocols[b].connector);c>-1&&a.splice(c,1)}var d=[];for(b in a)(!("required"in mist.data.capabilities.connectors[a[b]])||Object.keys(mist.data.capabilities.connectors[a[b]].required).length==0)&&d.push(a[b]);c="Click OK to enable disabled protocols with their default settings:\n "; ++c=d.length?c+d.join(", "):c+"None.";if(d.length!=a.length){a=a.filter(function(a){return d.indexOf(a)<0});c=c+("\n\nThe following protocols can only be set manually:\n "+a.join(", "))}if(confirm(c)&&d.length){if(mist.data.config.protocols===null)mist.data.config.protocols=[];for(b in d)mist.data.config.protocols.push({connector:d[b]});mist.send(function(){UI.navto("Protocols")},{config:mist.data.config})}})).append("<br>").append($("<button>").text("New protocol").click(function(){UI.navto("Edit Protocol")}).css("clear", ++"both")).append($("<table>").html($("<thead>").html($("<tr>").html($("<th>").text("Protocol")).append($("<th>").text("Status")).append($("<th>").text("Settings")).append($("<th>")))).append(D));var Ba=function(){function a(b){var c=mist.data.capabilities.connectors[b.connector];if(!c)return"";var d=[],e=["required","optional"],g;for(g in e)for(var E in c[e[g]])b[E]&&b[E]!=""?d.push(E+": "+b[E]):c[e[g]][E]["default"]&&d.push(E+": "+c[e[g]][E]["default"]);return $("<span>").addClass("description").text(d.join(", "))} ++D.html("");for(var b in mist.data.config.protocols){var c=mist.data.config.protocols[b],d=mist.data.capabilities.connectors[c.connector];D.append($("<tr>").data("index",b).append($("<td>").text(d&&d.friendly?d.friendly:c.connector)).append($("<td>").html(UI.format.status(c))).append($("<td>").html(a(c))).append($("<td>").css("text-align","right").html($("<button>").text("Edit").click(function(){UI.navto("Edit Protocol",$(this).closest("tr").data("index"))})).append($("<button>").text("Delete").click(function(){var a= ++$(this).closest("tr").data("index");if(confirm('Are you sure you want to delete the protocol "'+mist.data.config.protocols[a].connector+'"?')){mist.send(function(){UI.navto("Protocols")},{deleteprotocol:mist.data.config.protocols[a]});mist.data.config.protocols.splice(a,1)}}))))}};Ba();UI.interval.set(function(){mist.send(function(){Ba()})},1E4);break;case "Edit Protocol":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a,b)},{capabilities:!0});c.append("Loading..");return}var L= ++!1;""!=b&&0<=b&&(L=!0);var T={};for(r in mist.data.config.protocols)T[mist.data.config.protocols[r].connector]=1;var Ca=function(a){var b=mist.data.capabilities.connectors[a],c=mist.convertBuildOptions(b,p);if(L)var d=$.extend({},p);c.push({type:"hidden",pointer:{main:p,index:"connector"},value:a});c.push({type:"buttons",buttons:[{type:"save",label:"Save","function":function(){var a={};L?a.updateprotocol=[d,p]:a.addprotocol=p;mist.send(function(){UI.navto("Protocols")},a)}},{type:"cancel",label:"Cancel", ++"function":function(){UI.navto("Protocols")}}]});if("deps"in b&&b.deps!=""){j=$("<span>").text("Dependencies:");$ul=$("<ul>");j.append($ul);if(typeof b.deps=="string")b.deps=b.deps.split(", ");for(var e in b.deps){a=$("<li>").text(b.deps[e]+" ");$ul.append(a);typeof T[b.deps[e]]!="undefined"||typeof T[b.deps[e]+".exe"]!="undefined"?a.append($("<span>").addClass("green").text("(Configured)")):a.append($("<span>").addClass("red").text("(Not yet configured)"))}c.unshift({type:"text",text:j[0].innerHTML})}return UI.buildUI(c)}, ++T={};for(r in mist.data.config.protocols)T[mist.data.config.protocols[r].connector]=1;if(L){var s=mist.data.config.protocols[b],p=s;c.find("h2").append(' "'+s.connector+'"');c.append(Ca(s.connector))}else{c.html($("<h2>").text("New Protocol"));var p={},u=[["",""]];for(r in mist.data.capabilities.connectors)u.push([r,mist.data.capabilities.connectors[r].friendly?mist.data.capabilities.connectors[r].friendly:r]);var Q=$("<span>");c.append(UI.buildUI([{label:"Protocol",type:"select",select:u,"function":function(){$(this).getval()!= ++""&&Q.html(Ca($(this).getval()))}}])).append(Q)}break;case "Streams":if(!("capabilities"in mist.data)){c.html("Loading..");mist.send(function(){UI.navto(a)},{capabilities:!0});return}var Da=$("<button>"),M=$("<span>").text("Loading..");c.append(UI.buildUI([{type:"help",help:"Here you can create, edit or delete new and existing streams. Go to stream preview or embed a video player on your website."},$("<div>").css({width:"45.25em",display:"flex","justify-content":"flex-end"}).append(Da).append($("<button>").text("Create a new stream").click(function(){UI.navto("Edit")}))])).append(M); ++""==b&&(g=mist.stored.get(),"viewmode"in g&&(b=g.viewmode));Da.text("Switch to "+("thumbnails"==b?"list":"thumbnail")+" view").click(function(){mist.stored.set("viewmode",b=="thumbnails"?"list":"thumbnails");UI.navto("Streams",b=="thumbnails"?"list":"thumbnails")});var A=$.extend(!0,{},mist.data.streams),ja=function(a,b){var c=$.extend({},b);delete c.meta;delete c.error;c.online=2;c.name=a;c.ischild=true;return c},ka=function(b,d,e){M.remove();switch(b){case "thumbnails":var g=$("<div>").addClass("preview_icons"), ++f;f=e||[];d.sort();d.unshift("");M.remove();c.append($("<h2>").text(a)).append(UI.buildUI([{label:"Filter the streams",type:"datalist",datalist:d,pointer:{main:{},index:"stream"},help:"If you type something here, the box below will only show streams with names that contain your text.","function":function(){var a=$(this).val();g.children().each(function(){$(this).hide();$(this).attr("data-stream").indexOf(a)>-1&&$(this).show()})}}]));d.shift();c.append($("<span>").addClass("description").text("Choose a stream below.")).append(g); ++for(var h in d){var b=d[h],i="",j=$("<button>").text("Delete").click(function(){var a=$(this).closest("div").attr("data-stream");if(confirm('Are you sure you want to delete the stream "'+a+'"?')){delete mist.data.streams[a];var b={};b.deletestream=[a];mist.send(function(){UI.navto("Streams")},b)}}),k=$("<button>").text("Settings").click(function(){UI.navto("Edit",$(this).closest("div").attr("data-stream"))}),e=$("<button>").text("Preview").click(function(){UI.navto("Preview",$(this).closest("div").attr("data-stream"))}), ++l=$("<button>").text("Embed").click(function(){UI.navto("Embed",$(this).closest("div").attr("data-stream"))}),q=$("<span>").addClass("image");if(b.indexOf("+")>-1){i=b.split("+");i=mist.data.streams[i[0]].source+i[1];k=j="";q.addClass("wildcard")}else{i=mist.data.streams[b].source;if(f.indexOf(b)>-1){l=e="";q.addClass("folder")}}g.append($("<div>").append($("<span>").addClass("streamname").text(b)).append(q).append($("<span>").addClass("description").text(i)).append($("<span>").addClass("button_container").append(k).append(j).append(e).append(l)).attr("title", ++b).attr("data-stream",b))}break;default:var n=$("<tbody>").append($("<tr>").append("<td>").attr("colspan",6).text("Loading.."));h=$("<table>").html($("<thead>").html($("<tr>").html($("<th>").text("Stream name").attr("data-sort-type","string").addClass("sorting-asc")).append($("<th>").text("Source").attr("data-sort-type","string")).append($("<th>").text("Status").attr("data-sort-type","int")).append($("<th>").css("text-align","right").text("Connections").attr("data-sort-type","int")).append($("<th>")).append($("<th>")))).append(n); ++c.append(h);h.stupidtable();var m=function(){var a=[],b;for(b in mist.data.active_streams)a.push({streams:[mist.data.active_streams[b]],fields:["clients"],start:-2});mist.send(function(){$.extend(true,A,mist.data.streams);var a=0;n.html("");d.sort();for(var b in d){var c=d[b],e;e=c in mist.data.streams?mist.data.streams[c]:A[c];var g=$("<td>").css("text-align","right").html($("<span>").addClass("description").text("Loading..")),f=0;if(typeof mist.data.totals!="undefined"&&typeof mist.data.totals[c]!= ++"undefined"){var h=mist.data.totals[c].all_protocols.clients,f=0;if(h.length){for(a in h)f=f+h[a][1];f=Math.round(f/h.length)}}g.html(UI.format.number(f));if(f==0&&e.online==1)e.online=2;f=$("<td>").css("text-align","right").css("white-space","nowrap");(!("ischild"in e)||!e.ischild)&&f.html($("<button>").text("Settings").click(function(){UI.navto("Edit",$(this).closest("tr").data("index"))})).append($("<button>").text("Delete").click(function(){var a=$(this).closest("tr").data("index");if(confirm('Are you sure you want to delete the stream "'+ ++a+'"?')){delete mist.data.streams[a];var b={};mist.data.LTS?b.deletestream=[a]:b.streams=mist.data.streams;mist.send(function(){UI.navto("Streams")},b)}}));h=$("<span>").text(e.name);e.ischild&&h.css("padding-left","1em");var E=UI.format.status(e),i=$("<button>").text("Preview").click(function(){UI.navto("Preview",$(this).closest("tr").data("index"))}),q=$("<button>").text("Embed").click(function(){UI.navto("Embed",$(this).closest("tr").data("index"))});if("filesfound"in A[c]||e.online<0){E.html(""); ++i="";g.html("");q=""}n.append($("<tr>").data("index",c).html($("<td>").html(h).attr("title",e.name=="..."?"The results were truncated":e.name).addClass("overflow_ellipsis")).append($("<td>").text(e.source).attr("title",e.source).addClass("description").addClass("overflow_ellipsis").css("max-width","20em")).append($("<td>").data("sort-value",e.online).html(E)).append(g).append($("<td>").css("white-space","nowrap").html(i).append(q)).append(f));a++}},{totals:a,active_streams:true})};if(mist.data.LTS){var o= ++0,p=0;for(f in mist.data.streams){h=mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"];if(!h)break;if(mist.inputMatch(h.source_match,mist.data.streams[f].source)){A[f].source=A[f].source+"*";A[f].filesfound=null;mist.send(function(a,b){var c=b.stream,d=0,e;a:for(e in a.browse.files){var g;for(g in mist.data.capabilities.inputs)if(!(g.indexOf("Buffer")>=0||g.indexOf("Buffer.exe")>=0||g.indexOf("Folder")>=0||g.indexOf("Folder.exe")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[g].source_match, ++"/"+a.browse.files[e])){var f=c+"+"+a.browse.files[e];A[f]=ja(f,mist.data.streams[c]);A[f].source=mist.data.streams[c].source+a.browse.files[e];d++;if(d>=500){A[c+"+zzzzzzzzz"]={ischild:true,name:"...",online:-1};break a}}}"files"in a.browse&&a.browse.files.length?A[c].filesfound=true:mist.data.streams[c].filesfound=false;p++;if(o==p){mist.send(function(){m()},{active_streams:true});UI.interval.set(function(){m()},5E3)}},{browse:mist.data.streams[f].source},{stream:f});o++}}if(o==0){mist.send(function(){m()}, ++{active_streams:true});UI.interval.set(function(){m()},5E3)}}else{mist.send(function(){m()},{active_streams:true});UI.interval.set(function(){m()},5E3)}}};if(mist.data.LTS){var la=0,Ea=0,u={},Fa=[];for(g in mist.data.streams)if(mist.inputMatch((mist.data.capabilities.inputs.Folder||mist.data.capabilities.inputs["Folder.exe"]).source_match,mist.data.streams[g].source))Fa.push(g),mist.send(function(a,c){var d=c.stream,e=0,g;a:for(g in a.browse.files){var f;for(f in mist.data.capabilities.inputs)if(!(f.indexOf("Buffer")>= ++0||f.indexOf("Folder")>=0)&&mist.inputMatch(mist.data.capabilities.inputs[f].source_match,"/"+a.browse.files[g])){u[d+"+"+a.browse.files[g]]=true;e++;if(e>=500){u[d+"+zzzzzzzzz"]=true;break a}}}Ea++;la==Ea&&mist.send(function(){for(var a in mist.data.active_streams){var c=mist.data.active_streams[a].split("+");if(c.length>1&&c[0]in mist.data.streams){u[mist.data.active_streams[a]]=true;A[mist.data.active_streams[a]]=ja(mist.data.active_streams[a],mist.data.streams[c[0]])}}u=Object.keys(u);u=u.concat(Object.keys(mist.data.streams)); ++u.sort();ka(b,u,Fa)},{active_streams:true})},{browse:mist.data.streams[g].source},{stream:g}),la++;0==la&&mist.send(function(){for(var a in mist.data.active_streams){var c=mist.data.active_streams[a].split("+");if(c.length>1&&c[0]in mist.data.streams){u[mist.data.active_streams[a]]=true;A[mist.data.active_streams[a]]=ja(mist.data.active_streams[a],mist.data.streams[c[0]])}}u=Object.keys(u);mist.data.streams&&(u=u.concat(Object.keys(mist.data.streams)));u.sort();ka(b,u)},{active_streams:!0})}else ka(b, ++Object.keys(mist.data.streams));break;case "Edit":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a,b)},{capabilities:!0});c.append("Loading..");return}L=!1;""!=b&&(L=!0);if(L){var Ga=b,p=mist.data.streams[Ga];c.find("h2").append(' "'+Ga+'"')}else c.html($("<h2>").text("New Stream")),p={};var Ha=[];for(r in mist.data.capabilities.inputs)Ha.push(mist.data.capabilities.inputs[r].source_match);var ca=$("<div>"),Ia=function(a){var c={};if(!mist.data.streams)mist.data.streams= ++{};mist.data.streams[p.name]=p;b!=p.name&&delete mist.data.streams[b];c.addstream={};c.addstream[p.name]=p;if(b!=p.name)c.deletestream=[b];if(p.stop_sessions&&b!=""){c.stop_sessions=b;delete p.stop_sessions}mist.send(function(){delete mist.data.streams[p.name].online;delete mist.data.streams[p.name].error;UI.navto(a,a=="Preview"?p.name:"")},c)},Ja=$("<style>").text("button.saveandpreview { display: none; }"),N=$("<span>"),ma=function(){var a=c.find("[name=name]").val();if(a){var b=parseURL(mist.user.host), ++d=c.find("[name=source]").val(),e=d.match(/@.*/);e&&(e=e[0].substring(1));var g=d.replace(/(?:.+?):\/\//,""),g=g.split("/"),g=g[0],g=g.split(":"),g=g[0];(d=d.match(/:\d+/))&&(d=d[0]);var f={},h=["RTMP","RTSP","RTMP.exe","RTSP.exe"],i;for(i in h)h[i]in mist.data.capabilities.connectors&&(f[h[i]]=mist.data.capabilities.connectors[h[i]].optional.port["default"]);var h={RTMP:1935,"RTMP.exe":1935,RTSP:554,"RTSP.exe":554,TS:-1,"TS.exe":-1},j;for(j in f){for(i in mist.data.config.protocols){var k=mist.data.config.protocols[i]; ++if(k.connector==j){if("port"in k)f[j]=k.port;break}}f[j]=f[j]==h[j]?"":":"+f[j]}f.TS="";f["TS.exe"]="";N.find(".field").closest("label").hide();for(i in f){var q;j=d?d:f[i];switch(i){case "RTMP":case "RTMP.exe":q="rtmp://"+b.host+j+"/"+(e?e:"live")+"/";N.find(".field.RTMPurl").setval(q).closest("label").show();N.find(".field.RTMPkey").setval(a==""?"STREAMNAME":a).closest("label").show();q=q+(a==""?"STREAMNAME":a);break;case "RTSP":case "RTSP.exe":q="rtsp://"+b.host+j+"/"+(a==""?"STREAMNAME":a)+(e? ++"?pass="+e:"");break;case "TS":case "TS.exe":q="udp://"+(g==""?b.host:g)+j+"/"}N.find(".field."+i.replace(".exe","")).setval(q).closest("label").show()}}},Ka=$("<div>"),na={},u=[],La=$("<div>");for(r in mist.data.capabilities.processes)u.push([r,mist.data.capabilities.processes[r].hrn?mist.data.capabilities.processes[r].hrn:mist.data.capabilities.processes[r].name]);if(u.length){var ab=[{label:"New process",type:"select",select:u,value:u[0][0],pointer:{main:na,index:"process"},"function":function(){var a= ++$(this).getval();if(a!=null){var a=mist.data.capabilities.processes[a],b=[$("<h4>").text(a.name+" Process options")];La.html(UI.buildUI(b.concat(mist.convertBuildOptions(a,na))))}}},La];Ka.append(UI.buildUI([$("<br>"),$("<h3>").text("Stream processes"),{label:"Stream processes",itemLabel:"stream process",type:"sublist",sublist:ab,saveas:na,pointer:{main:p,index:"processes"}}]))}c.append(UI.buildUI([{label:"Stream name",type:"str",validate:["required","streamname"],pointer:{main:p,index:"name"},help:"Set the name this stream will be recognised by for players and/or stream pushing."}, ++{label:"Source",type:"browse",filetypes:Ha,pointer:{main:p,index:"source"},help:"<p> Below is the explanation of the input methods for MistServer. Anything between brackets () will go to default settings if not specified. </p> <table class=valigntop> <tr> <th colspan=3><b>File inputs</b></th> </tr> <tr> <th>File</th> <td> Linux/MacOS: /PATH/FILE<br> Windows: /cygdrive/DRIVE/PATH/FILE </td> <td> For file input please specify the proper path and file.<br> Supported inputs are: DTSC, FLV, MP3. MistServer Pro has TS, MP4, ISMV added as input. </td> </tr> <th> Folder </th> <td> Linux/MacOS: /PATH/<br> Windows: /cygdrive/DRIVE/PATH/ </td> <td> A folder stream makes all the recognised files in the selected folder available as a stream. </td> </tr> <tr><td colspan=3> </td></tr> <tr> <th colspan=3><b>Push inputs</b></th> </tr> <tr> <th>RTMP</th> <td>push://(IP)(@PASSWORD)</td> <td> IP is white listed IP for pushing towards MistServer, if left empty all are white listed.<br> PASSWORD is the application under which to push to MistServer, if it doesn't match the stream will be rejected. PASSWORD is MistServer Pro only. </td> </tr> <tr> <th>RTSP</th> <td>push://(IP)(@PASSWORD)</td> <td>IP is white listed IP for pushing towards MistServer, if left empty all are white listed.</td> </tr> <tr> <th>TS</th> <td>tsudp://(IP):PORT(/INTERFACE)</td> <td> IP is the IP address used to listen for this stream, multi-cast IP range is: 224.0.0.0 - 239.255.255.255. If IP is not set all addresses will listened to.<br> PORT is the port you reserve for this stream on the chosen IP.<br> INTERFACE is the interface used, if left all interfaces will be used. </td> </tr> <tr><td colspan=3> </td></tr> <tr> <th colspan=3><b>Pull inputs</b></th> </tr> <tr> <th>DTSC</th> <td>dtsc://MISTSERVER_IP:PORT/(STREAMNAME)</td> <td>MISTSERVER_IP is the IP of another MistServer to pull from.<br> PORT is the DTSC port of the other MistServer. (default is 4200)<br> STREAMNAME is the name of the target stream on the other MistServer. If left empty, the name of this stream will be used. </td> </tr> <tr> <th>HLS</th> <td>http://URL/TO/STREAM.m3u8</td> <td>The URL where the HLS stream is available to MistServer.</td> </tr> <tr> <th>RTSP</th> <td>rtsp://(USER:PASSWORD@)IP(:PORT)(/path)</td> <td> USER:PASSWORD is the account used if authorization is required.<br> IP is the IP address used to pull this stream from.<br> PORT is the port used to connect through.<br> PATH is the path to be used to identify the correct stream. </td> </tr> </table>", ++"function":function(){var a=$(this).val();Ja.remove();N.html("");if(a!=""){var b=null,d;for(d in mist.data.capabilities.inputs)if(typeof mist.data.capabilities.inputs[d].source_match!="undefined"&&mist.inputMatch(mist.data.capabilities.inputs[d].source_match,a)){b=d;break}if(b===null)ca.html($("<h3>").text("Unrecognized input").addClass("red")).append($("<span>").text("Please edit the stream source.").addClass("red"));else{b=mist.data.capabilities.inputs[b];ca.html($("<h3>").text(b.name+" Input options")); ++var e=mist.convertBuildOptions(b,p);"always_match"in mist.data.capabilities.inputs[d]&&mist.inputMatch(mist.data.capabilities.inputs[d].always_match,a)&&e.push({label:"Always on",type:"checkbox",help:"Keep this input available at all times, even when there are no active viewers.",pointer:{main:p,index:"always_on"}});ca.append(UI.buildUI(e));if(b.name=="Folder")c.append(Ja);else if(["Buffer","Buffer.exe","TS","TS.exe"].indexOf(b.name)>-1){d=[$("<br>"),$("<span>").text("Configure your source to push to:")]; + switch(b.name){case "Buffer":case "Buffer.exe":d.push({label:"RTMP full url",type:"span",clipboard:true,readonly:true,classes:["RTMP"],help:"Use this RTMP url if your client doesn't ask for a stream key"});d.push({label:"RTMP url",type:"span",clipboard:true,readonly:true,classes:["RTMPurl"],help:"Use this RTMP url if your client also asks for a stream key"});d.push({label:"RTMP stream key",type:"span",clipboard:true,readonly:true,classes:["RTMPkey"],help:"Use this key if your client asks for a stream key"}); +-d.push({label:"RTSP",type:"span",clipboard:true,readonly:true,classes:["RTSP"]});break;case "TS":case "TS.exe":a.charAt(0)=="/"?d=[]:d.push({label:"TS",type:"span",clipboard:true,readonly:true,classes:["TS"]})}N.html(UI.buildUI(d));na()}}}}},{label:"Stop sessions",type:"checkbox",help:"When saving these stream settings, kill this stream's current connections.",LTSonly:!0,pointer:{main:p,index:"stop_sessions"}},N,$("<br>"),{type:"custom",custom:da},Ka,{type:"buttons",buttons:[{type:"cancel",label:"Cancel", +-"function":function(){UI.navto("Streams")}},{type:"save",label:"Save","function":function(){Ia("Streams")}},{type:"save",label:"Save and Preview","function":function(){Ia("Preview")},classes:["saveandpreview"]}]}]));c.find("[name=name]").keyup(function(){na()});na();break;case "Preview":""==b&&UI.navto("Streams");var O=parseURL(mist.user.host),V=O.protocol,S=O.host,G=":8080",v=V+S+G+"/";for(r in mist.data.config.protocols)if(s=mist.data.config.protocols[r],"HTTP"==s.connector||"HTTP.exe"==s.connector){s.pubaddr&& +-s.pubaddr.length?"string"==typeof s.pubaddr?v=s.pubaddr.replace(/\/$/,"")+"/":s.pubaddr.length&&(v=s.pubaddr[0].replace(/\/$/,"")+"/"):(G=s.port?":"+s.port:":8080",v=V+S+G+"/");break}var R=$("<div>").css({display:"flex","flex-flow":"row wrap","flex-shrink":1,"min-width":"auto"}),W="";-1==b.indexOf("+")&&(W=$("<button>").text("Settings").addClass("settings").click(function(){UI.navto("Edit",b)}));c.html($("<div>").addClass("bigbuttons").append(W).append($("<button>").text("Embed").addClass("embed").click(function(){UI.navto("Embed", +-b)})).append($("<button>").addClass("cancel").addClass("return").text("Return").click(function(){UI.navto("Streams")}))).append($("<h2>").text('Preview of "'+b+'"')).append(R);var H=encodeURIComponent(b),Ma=$("<div>").css("flex-shrink","1").css("min-width","auto").css("max-width","100%");R.append(Ma);var Na=$("<div>"),X=$("<div>").text("Loading player..").css("max-width","100%").css("flex-shrink","1").css("min-width","auto"),pa=$("<div>").addClass("controls");Ma.append(X).append(Na).append(pa);$("link#devcss").length|| +-c.append($("<link>").attr("rel","stylesheet").attr("type","text/css").attr("href",v+"skins/dev.css").attr("id","devcss"));var Oa=function(){Na.text("");var d=document.createElement("script");c.append(d);d.src=v+"player.js";d.onerror=function(){X.html($("<p>").append('Failed to load <a href="'+v+'player.js">'+v+"player.js</a>.")).append($("<p>").append("Please check if you've activated the HTTP protocol, if your http port is blocked, or if you're trying to load HTTPS on an HTTP page.")).append($("<button>").text("Reload").css("display", +-"block").click(function(){Oa()}))};d.onload=function(){var e=b,f=function(){var a=MistVideoObject.reference;pa.html("");pa.append(a.UI.buildStructure({type:"container",classes:["mistvideo-column"],style:{flexShrink:1},children:[{"if":function(){return this.playerName&&this.source},then:{type:"container",classes:["mistvideo-description"],style:{display:"block"},children:[{type:"playername",style:{display:"inline"}},{type:"text",text:"is playing",style:{margin:"0 0.2em"}},{type:"mimetype"}]}},{type:"decodingIssues", ++d.push({label:"RTSP",type:"span",clipboard:true,readonly:true,classes:["RTSP"]});break;case "TS":case "TS.exe":a.charAt(0)=="/"?d=[]:d.push({label:"TS",type:"span",clipboard:true,readonly:true,classes:["TS"]})}N.html(UI.buildUI(d));ma()}}}}},{label:"Stop sessions",type:"checkbox",help:"When saving these stream settings, kill this stream's current connections.",pointer:{main:p,index:"stop_sessions"}},N,$("<br>"),{type:"custom",custom:ca},Ka,{type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Streams")}}, ++{type:"save",label:"Save","function":function(){Ia("Streams")}},{type:"save",label:"Save and Preview","function":function(){Ia("Preview")},classes:["saveandpreview"]}]}]));c.find("[name=name]").keyup(function(){ma()});ma();break;case "Preview":""==b&&UI.navto("Streams");var O=parseURL(mist.user.host),U=O.protocol,R=O.host,I=":8080",v=U+R+I+"/";for(r in mist.data.config.protocols)if(s=mist.data.config.protocols[r],"HTTP"==s.connector||"HTTP.exe"==s.connector){s.pubaddr&&s.pubaddr.length?"string"== ++typeof s.pubaddr?v=s.pubaddr.replace(/\/$/,"")+"/":s.pubaddr.length&&(v=s.pubaddr[0].replace(/\/$/,"")+"/"):(I=s.port?":"+s.port:":8080",v=U+R+I+"/");break}var Q=$("<div>").css({display:"flex","flex-flow":"row wrap","flex-shrink":1,"min-width":"auto"}),V="";-1==b.indexOf("+")&&(V=$("<button>").text("Settings").addClass("settings").click(function(){UI.navto("Edit",b)}));c.html($("<div>").addClass("bigbuttons").append(V).append($("<button>").text("Embed").addClass("embed").click(function(){UI.navto("Embed", ++b)})).append($("<button>").addClass("cancel").addClass("return").text("Return").click(function(){UI.navto("Streams")}))).append($("<h2>").text('Preview of "'+b+'"')).append(Q);var J=encodeURIComponent(b),Ma=$("<div>").css("flex-shrink","1").css("min-width","auto").css("max-width","100%");Q.append(Ma);var Na=$("<div>"),W=$("<div>").text("Loading player..").css("max-width","100%").css("flex-shrink","1").css("min-width","auto"),oa=$("<div>").addClass("controls");Ma.append(W).append(Na).append(oa);$("link#devcss").length|| ++c.append($("<link>").attr("rel","stylesheet").attr("type","text/css").attr("href",v+"skins/dev.css").attr("id","devcss"));var Oa=function(){Na.text("");var d=document.createElement("script");c.append(d);d.src=v+"player.js";d.onerror=function(){W.html($("<p>").append('Failed to load <a href="'+v+'player.js">'+v+"player.js</a>.")).append($("<p>").append("Please check if you've activated the HTTP protocol, if your http port is blocked, or if you're trying to load HTTPS on an HTTP page.")).append($("<button>").text("Reload").css("display", ++"block").click(function(){Oa()}))};d.onload=function(){var e=b,g=function(){var a=MistVideoObject.reference;oa.html("");oa.append(a.UI.buildStructure({type:"container",classes:["mistvideo-column"],style:{flexShrink:1},children:[{"if":function(){return this.playerName&&this.source},then:{type:"container",classes:["mistvideo-description"],style:{display:"block"},children:[{type:"playername",style:{display:"inline"}},{type:"text",text:"is playing",style:{margin:"0 0.2em"}},{type:"mimetype"}]}},{type:"decodingIssues", + style:{"max-width":"30em","flex-flow":"column nowrap"}},{type:"container",classes:["mistvideo-column","mistvideo-devcontrols"],children:[{type:"text",text:"Player control"},{type:"container",classes:["mistvideo-devbuttons"],style:{"flex-wrap":"wrap"},children:[{"if":function(){return!(!this.player||!this.player.api)},then:{type:"button",title:"Reload the video source",label:"Reload video",onclick:function(){this.player.api.load()}}},{type:"button",title:"Build MistVideo again",label:"Reload player", +-onclick:function(){this.reload()}},{type:"button",title:"Switch to the next available player and source combination",label:"Try next combination",onclick:function(){this.nextCombo()}}]},{type:"forcePlayer"},{type:"forceType"},{type:"forceSource"}]},{type:"log"}]}))};if(!(a!="Preview"||!b||b==""||e!=b)){X[0].addEventListener("initialized",f);X[0].addEventListener("initializeFailed",f);MistVideoObject.reference=mistPlay(e,{target:X[0],host:v,skin:"dev",loop:true,MistVideoObject:MistVideoObject})}c[0].removeChild(d)}; +-MistVideoObject.reference={unload:function(){d.onload=function(){this.parentElement&&this.parentElement.removeChild(this)}}}};Oa();var qa=$("<div>").append($("<h3>").text("Meta information")),ea=$("<span>").text("Loading..");qa.append(ea);var Pa=$("<div>").addClass("process_info");qa.append(Pa);R.append(qa);if(""!=H){$.ajax({type:"GET",url:v+"json_"+H+".js",success:function(a){var b=function(a,b){return"maxbps"in a?UI.format.bytes(a[b],1):b=="maxbps"?UI.format.bytes(a.bps,1):"unknown"},c=a.meta;if(!c|| +-!c.tracks)ea.html("No meta information available.");else{a=[];a.push({label:"Type",type:"span",value:c.live?"Live":"Pre-recorded (VoD)"});"format"in c&&a.push({label:"Format",type:"span",value:c.format});c.live&&a.push({label:"Buffer window",type:"span",value:UI.format.addUnit(c.buffer_window,"ms")});var d={audio:{vheader:"Audio",labels:["Codec","Duration","Avg bitrate","Peak bitrate","Channels","Samplerate","Language","Track index"],content:[]},video:{vheader:"Video",labels:["Codec","Duration","Avg bitrate", +-"Peak bitrate","Size","Framerate","Language","Track index","Has B-Frames"],content:[]},subtitle:{vheader:"Subtitles",labels:["Codec","Duration","Avg bitrate","Peak bitrate","Language","Track index"],content:[]}},e=Object.keys(c.tracks);e.sort(function(a,b){a=a.split("_").pop();b=b.split("_").pop();return a-b});var f=1,g=1,i=1,h;for(h in e){var j=e[h],q=c.tracks[j];switch(q.type){case "audio":d.audio.content.push({header:"Track "+j.split("_").pop(),body:[q.codec,UI.format.duration((q.lastms-q.firstms)/ +-1E3)+"<br><span class=description>"+UI.format.duration(q.firstms/1E3)+" to "+UI.format.duration(q.lastms/1E3)+"</span>",b(q,"bps"),b(q,"maxbps"),q.channels,UI.format.addUnit(UI.format.number(q.rate),"Hz"),"language"in q?q.language:"unknown",f]});f++;break;case "video":d.video.content.push({header:"Track "+j.split("_").pop(),body:[q.codec,UI.format.duration((q.lastms-q.firstms)/1E3)+"<br><span class=description>"+UI.format.duration(q.firstms/1E3)+" to "+UI.format.duration(q.lastms/1E3)+"</span>",b(q, +-"bps"),b(q,"maxbps"),UI.format.addUnit(q.width,"x ")+UI.format.addUnit(q.height,"px"),UI.format.addUnit(UI.format.number(q.fpks/1E3),"fps"),"language"in q?q.language:"unknown",g,"bframes"in q?"yes":"no"]});g++;break;case "meta":case "subtitle":if(q.codec=="subtitle"||q.type=="subtitle"){d.subtitle.content.push({header:"Track "+j.split("_").pop(),body:[q.codec,UI.format.duration((q.lastms-q.firstms)/1E3)+"<br><span class=description>"+UI.format.duration(q.firstms/1E3)+" to "+UI.format.duration(q.lastms/ +-1E3)+"</span>",b(q,"bps"),b(q,"maxbps"),"language"in q?q.language:"unknown",i]});i++}}}b=["audio","video","subtitle"];h=$("<div>").css({display:"flex","flex-flow":"row wrap","font-size":"0.9em"});for(j in b)d[b[j]].content.length&&h.append(UI.buildVheaderTable(d[b[j]]).css("width","auto"));a.push($("<span>").text("Tracks:"));a.push(h);ea.html(UI.buildUI(a))}},error:function(){ea.html("Error while retrieving stream info.")}});var Qa=function(){var a={proc_list:b};if(!mist.data.capabilities)a.capabilities= ++onclick:function(){this.reload()}},{type:"button",title:"Switch to the next available player and source combination",label:"Try next combination",onclick:function(){this.nextCombo()}}]},{type:"forcePlayer"},{type:"forceType"},{type:"forceSource"}]},{type:"log"}]}))};if(!(a!="Preview"||!b||b==""||e!=b)){W[0].addEventListener("initialized",g);W[0].addEventListener("initializeFailed",g);MistVideoObject.reference=mistPlay(e,{target:W[0],host:v,skin:"dev",loop:true,MistVideoObject:MistVideoObject})}c[0].removeChild(d)}; ++MistVideoObject.reference={unload:function(){d.onload=function(){this.parentElement&&this.parentElement.removeChild(this)}}}};Oa();var pa=$("<div>").append($("<h3>").text("Meta information")),da=$("<span>").text("Loading..");pa.append(da);var Pa=$("<div>").addClass("process_info");pa.append(Pa);Q.append(pa);if(""!=J){$.ajax({type:"GET",url:v+"json_"+J+".js",success:function(a){var b=function(a,b){return"maxbps"in a?UI.format.bytes(a[b],1):b=="maxbps"?UI.format.bytes(a.bps,1):"unknown"},c=a.meta;if(!c|| ++!c.tracks)da.html("No meta information available.");else{a=[];a.push({label:"Type",type:"span",value:c.live?"Live":"Pre-recorded (VoD)"});"format"in c&&a.push({label:"Format",type:"span",value:c.format});c.live&&a.push({label:"Buffer window",type:"span",value:UI.format.addUnit(c.buffer_window,"ms")});var d={audio:{vheader:"Audio",labels:["Codec","Duration","Avg bitrate","Peak bitrate","Channels","Samplerate","Language","Track index"],content:[]},video:{vheader:"Video",labels:["Codec","Duration","Avg bitrate", ++"Peak bitrate","Size","Framerate","Language","Track index","Has B-Frames"],content:[]},subtitle:{vheader:"Subtitles",labels:["Codec","Duration","Avg bitrate","Peak bitrate","Language","Track index"],content:[]}},e=Object.keys(c.tracks);e.sort(function(a,b){a=a.split("_").pop();b=b.split("_").pop();return a-b});var g=1,f=1,h=1,i;for(i in e){var j=e[i],q=c.tracks[j];switch(q.type){case "audio":d.audio.content.push({header:"Track "+j.split("_").pop(),body:[q.codec,UI.format.duration((q.lastms-q.firstms)/ ++1E3)+"<br><span class=description>"+UI.format.duration(q.firstms/1E3)+" to "+UI.format.duration(q.lastms/1E3)+"</span>",b(q,"bps"),b(q,"maxbps"),q.channels,UI.format.addUnit(UI.format.number(q.rate),"Hz"),"language"in q?q.language:"unknown",g]});g++;break;case "video":d.video.content.push({header:"Track "+j.split("_").pop(),body:[q.codec,UI.format.duration((q.lastms-q.firstms)/1E3)+"<br><span class=description>"+UI.format.duration(q.firstms/1E3)+" to "+UI.format.duration(q.lastms/1E3)+"</span>",b(q, ++"bps"),b(q,"maxbps"),UI.format.addUnit(q.width,"x ")+UI.format.addUnit(q.height,"px"),UI.format.addUnit(UI.format.number(q.fpks/1E3),"fps"),"language"in q?q.language:"unknown",f,"bframes"in q?"yes":"no"]});f++;break;case "meta":case "subtitle":if(q.codec=="subtitle"||q.type=="subtitle"){d.subtitle.content.push({header:"Track "+j.split("_").pop(),body:[q.codec,UI.format.duration((q.lastms-q.firstms)/1E3)+"<br><span class=description>"+UI.format.duration(q.firstms/1E3)+" to "+UI.format.duration(q.lastms/ ++1E3)+"</span>",b(q,"bps"),b(q,"maxbps"),"language"in q?q.language:"unknown",h]});h++}}}b=["audio","video","subtitle"];i=$("<div>").css({display:"flex","flex-flow":"row wrap","font-size":"0.9em"});for(j in b)d[b[j]].content.length&&i.append(UI.buildVheaderTable(d[b[j]]).css("width","auto"));a.push($("<span>").text("Tracks:"));a.push(i);da.html(UI.buildUI(a))}},error:function(){da.html("Error while retrieving stream info.")}});var Qa=function(){var a={proc_list:b};if(!mist.data.capabilities)a.capabilities= + true;mist.send(function(a){if(a.proc_list){var b=$("<table>").css("width","auto"),c={"Process type:":function(a){return $("<b>").text(a.process)},"Source:":function(a){var b=$("<span>").text(a.source);a.source_tracks&&a.source_tracks.length&&b.append($("<span>").addClass("description").text(" track "+a.source_tracks.slice(0,-2).concat(a.source_tracks.slice(-2).join(" and ")).join(", ")));return b},"Sink:":function(a){var b=$("<span>").text(a.sink);a.sink_tracks&&a.sink_tracks.length&&b.append($("<span>").addClass("description").text(" track "+ + a.sink_tracks.slice(0,-2).concat(a.sink_tracks.slice(-2).join(" and ")).join(", ")));return b},"Active for:":function(a){var b=(new Date).setSeconds((new Date).getSeconds()-a.active_seconds);return $("<span>").append($("<span>").text(UI.format.duration(a.active_seconds))).append($("<span>").addClass("description").text(" since "+UI.format.time(b/1E3)))},"Pid:":function(a,b){return b},"Logs:":function(a){var b=$("<div>").text("None.");if(a.logs&&a.logs.length){b.html("").addClass("description").css({overflow:"auto", + maxHeight:"6em",display:"flex",flexFlow:"column-reverse nowrap"});for(var c in a.logs){var d=a.logs[c];b.prepend($("<div>").append(UI.format.time(d[0])+" ["+d[1]+"] "+d[2]))}}return b},"Additional info:":function(a){var b;if(a.ainfo&&Object.keys(a.ainfo).length){b=$("<table>");for(var c in a.ainfo){var d=mist.data.capabilities.processes[a.process].ainfo[c];d||(d={name:c});b.append($("<tr>").append($("<th>").text(d.name+":")).append($("<td>").html(a.ainfo[c]).append(d.unit?$("<span>").addClass("unit").text(d.unit): +-"")))}}else b=$("<span>").addClass("description").text("N/A");return b}};Pa.html($("<h4>").text("Stream processes")).append(b);for(var d in c){var e=$("<tr>");b.append(e);e.append($("<th>").text(d).css("vertical-align","top"));for(var f in a.proc_list){$out=c[d](a.proc_list[f],f);e.append($("<td>").html($out).css("vertical-align","top"))}}}},a)};UI.interval.set(function(){Qa()},5E3);Qa()}break;case "Embed":""==b&&UI.navTo("Streams");W="";-1==b.indexOf("+")&&(W=$("<button>").addClass("settings").text("Settings").click(function(){UI.navto("Edit", +-b)}));c.html($("<div>").addClass("bigbuttons").append(W).append($("<button>").text("Preview").addClass("preview").click(function(){UI.navto("Preview",b)})).append($("<button>").addClass("cancel").addClass("return").text("Return").click(function(){UI.navto("Streams")}))).append($("<h2>").text('Embed "'+b+'"'));var Y=$("<span>");c.append(Y);var H=encodeURIComponent(b),O=parseURL(mist.user.host),V=O.protocol,S=O.host,G=":8080",Z,fa={},v={http:V+S+G+"/"};for(r in mist.data.config.protocols)if(s=mist.data.config.protocols[r], +-"HTTP"==s.connector||"HTTP.exe"==s.connector)s.pubaddr?("string"==typeof s.pubaddr?v.http=s.pubaddr.replace(/\/$/,"")+"/":s.pubaddr.length&&(v.http=s.pubaddr[0].replace(/\/$/,"")+"/"),fa.http=s.pubaddr):(G=s.port?":"+s.port:":8080",v.http=V+S+G+"/");else if("HTTPS"==s.connector||"HTTPS.exe"==s.connector)s.pubaddr&&s.pubaddr.length?("string"==typeof s.pubaddr?v.https=s.pubaddr.replace(/\/$/,"")+"/":s.pubaddr.length&&(v.https=s.pubaddr[0].replace(/\/$/,"")+"/"),fa.https=s.pubaddr):(Z=s.port?":"+s.port: +-":4433",v.https="https://"+S+Z+"/");var P=v.http,B={http:v.http};"https"in v&&(B.https=v.https);if(otherhost.host||otherhost.https){P=(otherhost.https&&Z?"https://":"http://")+(otherhost.host?otherhost.host:O.host)+(otherhost.https&&Z?Z:G)+"/";if(otherhost.host&&("http"in fa||(B.http=parseURL(B.http,{hostname:otherhost.host}).full),"https"in B&&!("https"in fa)))B.https=parseURL(B.https,{hostname:otherhost.host}).full;P=otherhost.https?B.https:B.http}var aa=!1,ra={forcePlayer:"",forceType:"",controls:!0, +-autoplay:!0,loop:!1,muted:!1,fillSpace:!1,poster:"",urlappend:"",setTracks:{}},n=$.extend({},ra),Ra=UI.stored.getOpts();"embedoptions"in Ra&&(n=$.extend(n,Ra.embedoptions,!0),"object"!=typeof n.setTracks&&(n.setTracks={}));var ga={};switch(n.controls){case "stock":ga.controls="stock";break;case !0:ga.controls=1;break;case !1:ga.controls=0}var y=function(){function a(b){switch(typeof b){case "string":return $.isNumeric(b)?b:'"'+b+'"';case "object":return JSON.stringify(b);default:return b}}aa&&UI.stored.saveOpt("embedoptions", +-n);for(var c=b+"_",d=12,e="";d--;){var f;f=Math.floor(Math.random()*62);f=f<10?f:f<36?String.fromCharCode(f+55):String.fromCharCode(f+61);e=e+f}var c=c+e,d=['target: document.getElementById("'+c+'")'],g;for(g in n)g=="prioritize_type"?n[g]&&n[g]!=""&&d.push("forcePriority: "+JSON.stringify({source:[["type",[n[g]]]]})):g=="monitor_action"?n[g]&&n[g]!=""&&n[g]=="nextCombo"&&d.push('monitor: {\n action: function(){\n this.MistVideo.log("Switching to nextCombo because of poor playback in "+this.MistVideo.source.type+" ("+Math.round(this.vars.score*1000)/10+"%)");\n this.MistVideo.nextCombo();\n }\n }'): +-n[g]!=ra[g]&&(n[g]!=null&&(typeof n[g]!="object"||JSON.stringify(n[g])!=JSON.stringify(ra[g])))&&d.push(g+": "+a(n[g]));g=[];g.push('<div class="mistvideo" id="'+c+'">');g.push(" <noscript>");g.push(' <a href="'+(otherhost.https?B.https:B.http)+H+'.html" target="_blank">');g.push(" Click here to play this video");g.push(" </a>");g.push(" </noscript>");g.push(" <script>");g.push(" var a = function(){");g.push(' mistPlay("'+b+'",{');g.push(" "+d.join(",\n "));g.push(" });"); +-g.push(" };");g.push(" if (!window.mistplayers) {");g.push(' var p = document.createElement("script");');if("https"in v&&parseURL(v.http).protocol!="https://"){g.push(' if (location.protocol == "https:") { p.src = "'+B.https+'player.js" } ');g.push(' else { p.src = "'+B.http+'player.js" } ')}else g.push(' p.src = "'+P+'player.js"');g.push(" document.head.appendChild(p);");g.push(" p.onload = a;");g.push(" }");g.push(" else { a(); }");g.push(" <\/script>"); +-g.push("</div>");return g.join("\n")},sa=$("<span>").text("Loading.."),Sa=y(n),T=$("<div>").text("Loading..").css("display","flex").css("flex-flow","column nowrap"),Ta="";"https"in v&&(Ta=UI.buildUI([{label:"Use HTTPS",type:"checkbox","function":function(){if($(this).getval()!=otherhost.https){otherhost.https=$(this).getval();UI.navto("Embed",b)}},value:otherhost.https}]).find("label"));Y.append($("<span>").addClass("input_container").append($("<label>").addClass("UIelement").append($("<span>").addClass("label").text("Use a different host:")).append($("<span>").addClass("field_container").append($("<input>").attr("type", +-"text").addClass("field").val(otherhost.host?otherhost.host:O.host)).append($("<span>").addClass("unit").append($("<button>").text("Apply").click(function(){otherhost.host=$(this).closest("label").find("input").val();UI.navto("Embed",b)}))))).append(Ta)).append(UI.buildUI([$("<h3>").text("Urls"),{label:"Stream info json",type:"str",value:P+"json_"+H+".js",readonly:!0,clipboard:!0,help:"Information about this stream as a json page."},{label:"Stream info script",type:"str",value:P+"info_"+H+".js",readonly:!0, +-clipboard:!0,help:"This script loads information about this stream into a mistvideo javascript object."},{label:"HTML page",type:"str",value:P+H+".html",readonly:!0,qrcode:!0,clipboard:!0,help:"A basic html containing the embedded stream."},$("<h3>").text("Embed code"),{label:"Embed code",type:"textarea",value:Sa,rows:Sa.split("\n").length+3,readonly:!0,classes:["embed_code"],clipboard:!0,help:"Include this code on your webpage to embed the stream. The options below can be used to configure how your content is displayed."}, +-$("<h4>").text("Embed code options (optional)").css("margin-top",0),{type:"help",help:"Use these controls to customise what this embedded video will look like.<br>Not all players have all of these options."},{label:"Prioritize type",type:"select",select:[["","Automatic"]],pointer:{main:n,index:"prioritize_type"},classes:["prioritize_type"],"function":function(){if(aa){n.prioritize_type=$(this).getval();$(".embed_code").setval(y(n))}},help:"Try to use this source type first, but full back to something else if it is not available."}, +-{label:"Force type",type:"select",select:[["","Automatic"]],pointer:{main:n,index:"forceType"},classes:["forceType"],"function":function(){if(aa){n.forceType=$(this).getval();$(".embed_code").setval(y(n))}},help:"Only use this particular source."},{label:"Force player",type:"select",select:[["","Automatic"]],pointer:{main:n,index:"forcePlayer"},classes:["forcePlayer"],"function":function(){if(aa){n.forcePlayer=$(this).getval();$(".embed_code").setval(y(n))}},help:"Only use this particular player."}, +-{label:"Controls",type:"select",select:[["1","MistServer Controls"],["stock","Player controls"],["0","None"]],pointer:{main:ga,index:"controls"},"function":function(){n.controls=$(this).getval()==1;switch($(this).getval()){case 0:n.controls=false;break;case 1:n.controls=true;break;case "stock":n.controls="stock"}$(".embed_code").setval(y(n))},help:"The type of controls that should be shown."},{label:"Autoplay",type:"checkbox",pointer:{main:n,index:"autoplay"},"function":function(){n.autoplay=$(this).getval(); +-$(".embed_code").setval(y(n))},help:"Whether or not the video should play as the page is loaded."},{label:"Loop",type:"checkbox",pointer:{main:n,index:"loop"},"function":function(){n.loop=$(this).getval();$(".embed_code").setval(y(n))},help:"If the video should restart when the end is reached."},{label:"Start muted",type:"checkbox",pointer:{main:n,index:"muted"},"function":function(){n.muted=$(this).getval();$(".embed_code").setval(y(n))},help:"If the video should restart when the end is reached."}, +-{label:"Fill available space",type:"checkbox",pointer:{main:n,index:"fillSpace"},"function":function(){n.fillSpace=$(this).getval();$(".embed_code").setval(y(n))},help:"The video will fit the available space in its container, even if the video stream has a smaller resolution."},{label:"Poster",type:"str",pointer:{main:n,index:"poster"},"function":function(){n.poster=$(this).getval();$(".embed_code").setval(y(n))},help:"URL to an image that is displayed when the video is not playing."},{label:"Video URL addition", +-type:"str",pointer:{main:n,index:"urlappend"},help:"The embed script will append this string to the video url, useful for sending through params.",classes:["embed_code_forceprotocol"],"function":function(){n.urlappend=$(this).getval();$(".embed_code").setval(y(n))}},{label:"Preselect tracks",type:"DOMfield",DOMfield:T,help:"Pre-select these tracks."},{label:"Monitoring action",type:"select",select:[["","Ask the viewer what to do"],["nextCombo","Try the next source / player combination"]],pointer:{main:n, +-index:"monitor_action"},"function":function(){n.monitor_action=$(this).getval();$(".embed_code").setval(y(n))},help:"What the player should do when playback is poor."},$("<h3>").text("Protocol stream urls"),sa]));$.ajax({type:"GET",url:P+"json_"+H+".js",success:function(a){var b=[],c=Y.find(".field.forceType"),d=Y.find(".field.prioritize_type"),e;for(e in a.source){var g=a.source[e],f=UI.humanMime(g.type);b.push({label:f?f+" <span class=description>("+g.type+")</span>":UI.format.capital(g.type),type:"str", +-value:g.url,readonly:true,qrcode:true,clipboard:true});f=UI.humanMime(g.type);if(c.children('option[value="'+g.type+'"]').length==0){c.append($("<option>").text(f?f+" ("+g.type+")":UI.format.capital(g.type)).val(g.type));d.append($("<option>").text(f?f+" ("+g.type+")":UI.format.capital(g.type)).val(g.type))}}c.val(n.forceType);d.val(n.prioritize_type);sa.html(UI.buildUI(b));T.html("");b={};for(e in a.meta.tracks){c=a.meta.tracks[e];if(c.codec=="subtitle")c.type="subtitle";if(!(c.type!="audio"&&c.type!= +-"video"&&c.type!="subtitle")){c.type in b||(b[c.type]=c.type=="subtitle"?[]:[["","Autoselect "+c.type]]);b[c.type].push([c.trackid,UI.format.capital(c.type)+" track "+(b[c.type].length+(c.type=="subtitle"?1:0))])}}if(Object.keys(b).length){T.closest("label").show();var a=["audio","video","subtitle"],h;for(h in a){e=a[h];if(b[e]&&b[e].length){c=$("<select>").attr("data-type",e).css("flex-grow","1").change(function(){$(this).val()==""?delete n.setTracks[$(this).attr("data-type")]:n.setTracks[$(this).attr("data-type")]= +-$(this).val();$(".embed_code").setval(y(n))});T.append(c);e=="subtitle"?b[e].unshift(["","No "+e]):b[e].push([-1,"No "+e]);for(var i in b[e])c.append($("<option>").val(b[e][i][0]).text(b[e][i][1]));if(e in n.setTracks){c.val(n.setTracks[e]);if(c.val()==null){c.val("");delete n.setTracks[e];$(".embed_code").setval(y(n))}}}}}else T.closest("label").hide();aa=true},error:function(){sa.html("Error while retrieving stream info.");T.closest("label").hide();n.setTracks={}}});var ha=document.createElement("script"); +-ha.src=v.http+"player.js";document.head.appendChild(ha);ha.onload=function(){var a=Y.find(".field.forcePlayer"),b;for(b in mistplayers)a.append($("<option>").text(mistplayers[b].name).val(b));document.head.removeChild(this)};ha.onerror=function(){document.head.removeChild(this)};break;case "Push":var I=$("<div>").text("Loading..");c.append(I);mist.send(function(a){function b(a){setTimeout(function(){mist.send(function(c){var d=false;if("push_list"in c&&c.push_list&&c.push_list.length){var d=true, +-g;for(g in c.push_list)if(a.indexOf(c.push_list[g][0])>-1){d=false;break}}else d=true;if(d)for(g in a)e.find("tr[data-pushid="+a[g]+"]").remove();else b()},{push_list:1})},1E3)}function c(g,f){var h=$("<span>"),i=$("<span>");if(f=="Automatic"&&g.length>=4){h.append($("<span>").text(g[2]));g[3]&&h.append($("<span>").text(", schedule on "+(new Date(g[3]*1E3)).toLocaleString()));g.length>=5&&g[4]&&h.append($("<span>").text(", complete on "+(new Date(g[4]*1E3)).toLocaleString()))}else g.length>=4&&g[2]!= +-g[3]?h.append($("<span>").text(g[2])).append($("<span>").html("»").addClass("unit").css("margin","0 0.5em")).append($("<span>").text(g[3])):h.append($("<span>").text(g[2]));var j=$("<td>").append($("<button>").text(f=="Automatic"?"Remove":"Stop").click(function(){if(confirm("Are you sure you want to "+$(this).text().toLowerCase()+" this push?\n"+g[1]+" to "+g[2])){var a=$(this).closest("tr");a.html($("<td colspan=99>").html($("<span>").addClass("red").text(f=="Automatic"?"Removing..":"Stopping.."))); +-if(f=="Automatic"){var c=g.slice(1);mist.send(function(){a.remove()},{push_auto_remove:[c]})}else mist.send(function(){b([g[0]])},{push_stop:[g[0]]})}}));if(f=="Automatic"){j.prepend($("<button>").text("Edit").click(function(){UI.navto("Start Push","auto_"+($(this).closest("tr").index()-1))}));j.append($("<button>").text("Stop pushes").click(function(){if(confirm('Are you sure you want to stop all pushes matching \n"'+g[1]+" to "+g[2]+'"?'+(d.wait!=0?"\n\nRetrying is enabled. You'll probably want to set that to 0.": +-""))){var c=$(this);c.text("Stopping pushes..");var f=[],h;for(h in a.push_list)if(g[1]==a.push_list[h][1]&&g[2]==a.push_list[h][2]){f.push(a.push_list[h][0]);e.find("tr[data-pushid="+a.push_list[h][0]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}mist.send(function(){c.text("Stop pushes");b(f)},{push_stop:f,push_settings:{wait:0}})}}))}else{if(g.length>=6){var k=g[5];i.append($("<div>").append("Active for: "+UI.format.duration(k.active_seconds))).append($("<div>").append("Data transfered: "+ +-UI.format.bytes(k.bytes))).append($("<div>").append("Media time transfered: "+UI.format.duration(k.mediatime*0.001)));"pkt_retrans_count"in k&&i.append($("<div>").append("Packets retransmitted: "+UI.format.number(k.pkt_retrans_count||0)));"pkt_loss_count"in k&&i.append($("<div>").append("Packets lost: "+UI.format.number(k.pkt_loss_count||0)+" ("+UI.format.addUnit(UI.format.number(k.pkt_loss_perc||0),"%")+" over the last "+UI.format.addUnit(5,"s")+")"))}if(g.length>=5)for(var l in g[4]){k=g[4][l]; +-i.append($("<div>").append(UI.format.time(k[0])+" ["+k[1]+"] "+k[2]))}}return $("<tr>").css("vertical-align","top").attr("data-pushid",g[0]).append($("<td>").text(g[1])).append($("<td>").append(h.children())).append($("<td>").addClass("logs").append(i.children())).append(j)}I.html(UI.buildUI([{type:"help",help:"You can push streams to files or other servers, allowing them to broadcast your stream as well."}]));var d=a.push_settings;d||(d={});var e=$("<table>").append($("<tr>").append($("<th>").text("Stream")).append($("<th>").text("Target")).append($("<th>")).append($("<th>"))), +-g=e.clone();if("push_list"in a)for(var f in a.push_list)e.append(c(a.push_list[f],"Manual"));if("push_auto_list"in a)for(f in a.push_auto_list){var h=a.push_auto_list[f].slice();h.unshift(-1);g.append(c(h,"Automatic"))}I.append($("<h3>").text("Automatic pushes")).append(UI.buildUI([{label:"Delay before retry",unit:"s",type:"int",min:0,help:"How long the delay should be before MistServer retries an automatic push.<br>If set to 0, it does not retry.","default":0,pointer:{main:d,index:"wait"},LTSonly:1}, +-{label:"Maximum retries",unit:"/s",type:"int",min:0,help:"The maximum amount of retries per second (for all automatic pushes).<br>If set to 0, there is no limit.","default":0,pointer:{main:d,index:"maxspeed"},LTSonly:1},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){mist.send(function(){UI.navto("Push")},{push_settings:d})}}]}])).append($("<button>").text("Add an automatic push").click(function(){UI.navto("Start Push","auto")}));g.find("tr").length==1?I.append($("<div>").text("No automatic pushes have been configured.").addClass("text").css("margin-top", +-"0.5em")):I.append(g);I.append($("<h3>").text("Pushes")).append($("<button>").text("Start a push").click(function(){UI.navto("Start Push")}));if(e.find("tr").length==1)I.append($("<div>").text("No pushes are active.").addClass("text").css("margin-top","0.5em"));else{var g=[],h=[],i=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any stream").val("")),j=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any target").val(""));for(f in a.push_list){g.indexOf(a.push_list[f][1])== +--1&&g.push(a.push_list[f][1]);h.indexOf(a.push_list[f][2])==-1&&h.push(a.push_list[f][2])}g.sort();h.sort();for(f in g)i.append($("<option>").text(g[f]));for(f in h)j.append($("<option>").text(h[f]));I.append($("<button>").text("Stop all pushes").click(function(){var c=[],d;for(d in a.push_list)c.push(a.push_list[d][0]);if(c.length!=0&&confirm("Are you sure you want to stop all pushes?")){mist.send(function(){b(c)},{push_stop:c});e.find("tr:not(:first-child)").html($("<td colspan=99>").append($("<span>").addClass("red").text("Stopping.."))); +-$(this).remove()}})).append($("<label>").css("margin-left","1em").append($("<span>").text("Stop all pushes that match: ").css("font-size","0.9em")).append(i).append($("<span>").css("margin-left","0.5em").text("and").css("font-size","0.9em")).append(j).append($("<button>").css("margin-left","0.5em").text("Apply").click(function(){var c=i.val(),d=j.val();if(c==""&&d=="")return alert("Looks like you want to stop all pushes. Maybe you should use that button?");var g={},f;for(f in a.push_list)if((c==""|| +-a.push_list[f][1]==c)&&(d==""||a.push_list[f][2]==d))g[a.push_list[f][0]]=a.push_list[f];if(Object.keys(g).length==0)return alert("No matching pushes.");c="Are you sure you want to stop these pushes?\n\n";for(f in g)c=c+(g[f][1]+" to "+g[f][2]+"\n");if(confirm(c)){g=Object.keys(g);mist.send(function(){b(g)},{push_stop:g});for(f in g)e.find("tr[data-pushid="+g[f]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}}))).append(e)}UI.interval.set(function(){mist.send(function(a){var b= +-e.find("tr").first();e.empty();e.append(b);for(var d in a.push_list)e.append(c(a.push_list[d]))},{push_list:1})},5E3)},{push_settings:1,push_list:1,push_auto_list:1});break;case "Start Push":if(!("capabilities"in mist.data)){c.append("Loading Mist capabilities..");mist.send(function(){UI.navto("Start Push",b)},{capabilities:1});return}var x,ia=function(a){var d=false,g=b.split("_");b=g[0];g.length==2&&(d=g[1]);if(d!==false&&typeof a=="undefined")mist.send(function(a){ia(a.push_auto_list[d])},{push_auto_list:1}); +-else{var e=[],f={},h;for(h in mist.data.capabilities.connectors){g=mist.data.capabilities.connectors[h];if("push_urls"in g){e=e.concat(g.push_urls);f[h]=g.push_urls}}b=="auto"&&c.find("h2").text("Add automatic push");var i={params:{}};if(b=="auto"&&typeof a!="undefined"){i={stream:a[0],target:a[1],params:{}};g=i.target.split("?");if(g.length>1){params=g.pop();i.target=g.join("?");params=params.split("&");for(h in params){g=params[h].split("=");i.params[g.shift()]=g.join("=")}}}var j=$("<div>").css("margin", ++"")))}}else b=$("<span>").addClass("description").text("N/A");return b}};Pa.html($("<h4>").text("Stream processes")).append(b);for(var d in c){var e=$("<tr>");b.append(e);e.append($("<th>").text(d).css("vertical-align","top"));for(var g in a.proc_list){$out=c[d](a.proc_list[g],g);e.append($("<td>").html($out).css("vertical-align","top"))}}}},a)};UI.interval.set(function(){Qa()},5E3);Qa()}break;case "Embed":""==b&&UI.navTo("Streams");V="";-1==b.indexOf("+")&&(V=$("<button>").addClass("settings").text("Settings").click(function(){UI.navto("Edit", ++b)}));c.html($("<div>").addClass("bigbuttons").append(V).append($("<button>").text("Preview").addClass("preview").click(function(){UI.navto("Preview",b)})).append($("<button>").addClass("cancel").addClass("return").text("Return").click(function(){UI.navto("Streams")}))).append($("<h2>").text('Embed "'+b+'"'));var X=$("<span>");c.append(X);var J=encodeURIComponent(b),O=parseURL(mist.user.host),U=O.protocol,R=O.host,I=":8080",Y,ea={},v={http:U+R+I+"/"};for(r in mist.data.config.protocols)if(s=mist.data.config.protocols[r], ++"HTTP"==s.connector||"HTTP.exe"==s.connector)s.pubaddr?("string"==typeof s.pubaddr?v.http=s.pubaddr.replace(/\/$/,"")+"/":s.pubaddr.length&&(v.http=s.pubaddr[0].replace(/\/$/,"")+"/"),ea.http=s.pubaddr):(I=s.port?":"+s.port:":8080",v.http=U+R+I+"/");else if("HTTPS"==s.connector||"HTTPS.exe"==s.connector)s.pubaddr&&s.pubaddr.length?("string"==typeof s.pubaddr?v.https=s.pubaddr.replace(/\/$/,"")+"/":s.pubaddr.length&&(v.https=s.pubaddr[0].replace(/\/$/,"")+"/"),ea.https=s.pubaddr):(Y=s.port?":"+s.port: ++":4433",v.https="https://"+R+Y+"/");var P=v.http,B={http:v.http};"https"in v&&(B.https=v.https);if(otherhost.host||otherhost.https){P=(otherhost.https&&Y?"https://":"http://")+(otherhost.host?otherhost.host:O.host)+(otherhost.https&&Y?Y:I)+"/";if(otherhost.host&&("http"in ea||(B.http=parseURL(B.http,{hostname:otherhost.host}).full),"https"in B&&!("https"in ea)))B.https=parseURL(B.https,{hostname:otherhost.host}).full;P=otherhost.https?B.https:B.http}var Z=!1,qa={forcePlayer:"",forceType:"",controls:!0, ++autoplay:!0,loop:!1,muted:!1,fillSpace:!1,poster:"",urlappend:"",setTracks:{}},o=$.extend({},qa),Ra=UI.stored.getOpts();"embedoptions"in Ra&&(o=$.extend(o,Ra.embedoptions,!0),"object"!=typeof o.setTracks&&(o.setTracks={}));var fa={};switch(o.controls){case "stock":fa.controls="stock";break;case !0:fa.controls=1;break;case !1:fa.controls=0}var y=function(){function a(b){switch(typeof b){case "string":return $.isNumeric(b)?b:'"'+b+'"';case "object":return JSON.stringify(b);default:return b}}Z&&UI.stored.saveOpt("embedoptions", ++o);for(var c=b+"_",d=12,e="";d--;){var g;g=Math.floor(Math.random()*62);g=g<10?g:g<36?String.fromCharCode(g+55):String.fromCharCode(g+61);e=e+g}var c=c+e,d=['target: document.getElementById("'+c+'")'],f;for(f in o)f=="prioritize_type"?o[f]&&o[f]!=""&&d.push("forcePriority: "+JSON.stringify({source:[["type",[o[f]]]]})):f=="monitor_action"?o[f]&&o[f]!=""&&o[f]=="nextCombo"&&d.push('monitor: {\n action: function(){\n this.MistVideo.log("Switching to nextCombo because of poor playback in "+this.MistVideo.source.type+" ("+Math.round(this.vars.score*1000)/10+"%)");\n this.MistVideo.nextCombo();\n }\n }'): ++o[f]!=qa[f]&&(o[f]!=null&&(typeof o[f]!="object"||JSON.stringify(o[f])!=JSON.stringify(qa[f])))&&d.push(f+": "+a(o[f]));f=[];f.push('<div class="mistvideo" id="'+c+'">');f.push(" <noscript>");f.push(' <a href="'+(otherhost.https?B.https:B.http)+J+'.html" target="_blank">');f.push(" Click here to play this video");f.push(" </a>");f.push(" </noscript>");f.push(" <script>");f.push(" var a = function(){");f.push(' mistPlay("'+b+'",{');f.push(" "+d.join(",\n "));f.push(" });"); ++f.push(" };");f.push(" if (!window.mistplayers) {");f.push(' var p = document.createElement("script");');if("https"in v&&parseURL(v.http).protocol!="https://"){f.push(' if (location.protocol == "https:") { p.src = "'+B.https+'player.js" } ');f.push(' else { p.src = "'+B.http+'player.js" } ')}else f.push(' p.src = "'+P+'player.js"');f.push(" document.head.appendChild(p);");f.push(" p.onload = a;");f.push(" }");f.push(" else { a(); }");f.push(" <\/script>"); ++f.push("</div>");return f.join("\n")},ra=$("<span>").text("Loading.."),Sa=y(o),S=$("<div>").text("Loading..").css("display","flex").css("flex-flow","column nowrap"),Ta="";"https"in v&&(Ta=UI.buildUI([{label:"Use HTTPS",type:"checkbox","function":function(){if($(this).getval()!=otherhost.https){otherhost.https=$(this).getval();UI.navto("Embed",b)}},value:otherhost.https}]).find("label"));X.append($("<span>").addClass("input_container").append($("<label>").addClass("UIelement").append($("<span>").addClass("label").text("Use a different host:")).append($("<span>").addClass("field_container").append($("<input>").attr("type", ++"text").addClass("field").val(otherhost.host?otherhost.host:O.host)).append($("<span>").addClass("unit").append($("<button>").text("Apply").click(function(){otherhost.host=$(this).closest("label").find("input").val();UI.navto("Embed",b)}))))).append(Ta)).append(UI.buildUI([$("<h3>").text("Urls"),{label:"Stream info json",type:"str",value:P+"json_"+J+".js",readonly:!0,clipboard:!0,help:"Information about this stream as a json page."},{label:"Stream info script",type:"str",value:P+"info_"+J+".js",readonly:!0, ++clipboard:!0,help:"This script loads information about this stream into a mistvideo javascript object."},{label:"HTML page",type:"str",value:P+J+".html",readonly:!0,qrcode:!0,clipboard:!0,help:"A basic html containing the embedded stream."},$("<h3>").text("Embed code"),{label:"Embed code",type:"textarea",value:Sa,rows:Sa.split("\n").length+3,readonly:!0,classes:["embed_code"],clipboard:!0,help:"Include this code on your webpage to embed the stream. The options below can be used to configure how your content is displayed."}, ++$("<h4>").text("Embed code options (optional)").css("margin-top",0),{type:"help",help:"Use these controls to customise what this embedded video will look like.<br>Not all players have all of these options."},{label:"Prioritize type",type:"select",select:[["","Automatic"]],pointer:{main:o,index:"prioritize_type"},classes:["prioritize_type"],"function":function(){if(Z){o.prioritize_type=$(this).getval();$(".embed_code").setval(y(o))}},help:"Try to use this source type first, but full back to something else if it is not available."}, ++{label:"Force type",type:"select",select:[["","Automatic"]],pointer:{main:o,index:"forceType"},classes:["forceType"],"function":function(){if(Z){o.forceType=$(this).getval();$(".embed_code").setval(y(o))}},help:"Only use this particular source."},{label:"Force player",type:"select",select:[["","Automatic"]],pointer:{main:o,index:"forcePlayer"},classes:["forcePlayer"],"function":function(){if(Z){o.forcePlayer=$(this).getval();$(".embed_code").setval(y(o))}},help:"Only use this particular player."}, ++{label:"Controls",type:"select",select:[["1","MistServer Controls"],["stock","Player controls"],["0","None"]],pointer:{main:fa,index:"controls"},"function":function(){o.controls=$(this).getval()==1;switch($(this).getval()){case 0:o.controls=false;break;case 1:o.controls=true;break;case "stock":o.controls="stock"}$(".embed_code").setval(y(o))},help:"The type of controls that should be shown."},{label:"Autoplay",type:"checkbox",pointer:{main:o,index:"autoplay"},"function":function(){o.autoplay=$(this).getval(); ++$(".embed_code").setval(y(o))},help:"Whether or not the video should play as the page is loaded."},{label:"Loop",type:"checkbox",pointer:{main:o,index:"loop"},"function":function(){o.loop=$(this).getval();$(".embed_code").setval(y(o))},help:"If the video should restart when the end is reached."},{label:"Start muted",type:"checkbox",pointer:{main:o,index:"muted"},"function":function(){o.muted=$(this).getval();$(".embed_code").setval(y(o))},help:"If the video should restart when the end is reached."}, ++{label:"Fill available space",type:"checkbox",pointer:{main:o,index:"fillSpace"},"function":function(){o.fillSpace=$(this).getval();$(".embed_code").setval(y(o))},help:"The video will fit the available space in its container, even if the video stream has a smaller resolution."},{label:"Poster",type:"str",pointer:{main:o,index:"poster"},"function":function(){o.poster=$(this).getval();$(".embed_code").setval(y(o))},help:"URL to an image that is displayed when the video is not playing."},{label:"Video URL addition", ++type:"str",pointer:{main:o,index:"urlappend"},help:"The embed script will append this string to the video url, useful for sending through params.",classes:["embed_code_forceprotocol"],"function":function(){o.urlappend=$(this).getval();$(".embed_code").setval(y(o))}},{label:"Preselect tracks",type:"DOMfield",DOMfield:S,help:"Pre-select these tracks."},{label:"Monitoring action",type:"select",select:[["","Ask the viewer what to do"],["nextCombo","Try the next source / player combination"]],pointer:{main:o, ++index:"monitor_action"},"function":function(){o.monitor_action=$(this).getval();$(".embed_code").setval(y(o))},help:"What the player should do when playback is poor."},$("<h3>").text("Protocol stream urls"),ra]));$.ajax({type:"GET",url:P+"json_"+J+".js",success:function(a){var b=[],c=X.find(".field.forceType"),d=X.find(".field.prioritize_type"),e;for(e in a.source){var f=a.source[e],g=UI.humanMime(f.type);b.push({label:g?g+" <span class=description>("+f.type+")</span>":UI.format.capital(f.type),type:"str", ++value:f.url,readonly:true,qrcode:true,clipboard:true});g=UI.humanMime(f.type);if(c.children('option[value="'+f.type+'"]').length==0){c.append($("<option>").text(g?g+" ("+f.type+")":UI.format.capital(f.type)).val(f.type));d.append($("<option>").text(g?g+" ("+f.type+")":UI.format.capital(f.type)).val(f.type))}}c.val(o.forceType);d.val(o.prioritize_type);ra.html(UI.buildUI(b));S.html("");b={};for(e in a.meta.tracks){c=a.meta.tracks[e];if(c.codec=="subtitle")c.type="subtitle";if(!(c.type!="audio"&&c.type!= ++"video"&&c.type!="subtitle")){c.type in b||(b[c.type]=c.type=="subtitle"?[]:[["","Autoselect "+c.type]]);b[c.type].push([c.trackid,UI.format.capital(c.type)+" track "+(b[c.type].length+(c.type=="subtitle"?1:0))])}}if(Object.keys(b).length){S.closest("label").show();var a=["audio","video","subtitle"],h;for(h in a){e=a[h];if(b[e]&&b[e].length){c=$("<select>").attr("data-type",e).css("flex-grow","1").change(function(){$(this).val()==""?delete o.setTracks[$(this).attr("data-type")]:o.setTracks[$(this).attr("data-type")]= ++$(this).val();$(".embed_code").setval(y(o))});S.append(c);e=="subtitle"?b[e].unshift(["","No "+e]):b[e].push([-1,"No "+e]);for(var i in b[e])c.append($("<option>").val(b[e][i][0]).text(b[e][i][1]));if(e in o.setTracks){c.val(o.setTracks[e]);if(c.val()==null){c.val("");delete o.setTracks[e];$(".embed_code").setval(y(o))}}}}}else S.closest("label").hide();Z=true},error:function(){ra.html("Error while retrieving stream info.");S.closest("label").hide();o.setTracks={}}});var ga=document.createElement("script"); ++ga.src=v.http+"player.js";document.head.appendChild(ga);ga.onload=function(){var a=X.find(".field.forcePlayer"),b;for(b in mistplayers)a.append($("<option>").text(mistplayers[b].name).val(b));document.head.removeChild(this)};ga.onerror=function(){document.head.removeChild(this)};break;case "Push":var K=$("<div>").text("Loading..");c.append(K);mist.send(function(a){function b(a){setTimeout(function(){mist.send(function(c){var d=false;if("push_list"in c&&c.push_list&&c.push_list.length){var d=true, ++f;for(f in c.push_list)if(a.indexOf(c.push_list[f][0])>-1){d=false;break}}else d=true;if(d)for(f in a)e.find("tr[data-pushid="+a[f]+"]").remove();else b()},{push_list:1})},1E3)}function c(f,g){var h=$("<span>"),i=$("<span>");if(g=="Automatic"&&f.length>=4){h.append($("<span>").text(f[2]));f[3]&&h.append($("<span>").text(", schedule on "+(new Date(f[3]*1E3)).toLocaleString()));f.length>=5&&f[4]&&h.append($("<span>").text(", complete on "+(new Date(f[4]*1E3)).toLocaleString()))}else f.length>=4&&f[2]!= ++f[3]?h.append($("<span>").text(f[2])).append($("<span>").html("»").addClass("unit").css("margin","0 0.5em")).append($("<span>").text(f[3])):h.append($("<span>").text(f[2]));var j=$("<td>").append($("<button>").text(g=="Automatic"?"Remove":"Stop").click(function(){if(confirm("Are you sure you want to "+$(this).text().toLowerCase()+" this push?\n"+f[1]+" to "+f[2])){var a=$(this).closest("tr");a.html($("<td colspan=99>").html($("<span>").addClass("red").text(g=="Automatic"?"Removing..":"Stopping.."))); ++if(g=="Automatic"){var c=f.slice(1);mist.send(function(){a.remove()},{push_auto_remove:[c]})}else mist.send(function(){b([f[0]])},{push_stop:[f[0]]})}}));if(g=="Automatic"){j.prepend($("<button>").text("Edit").click(function(){UI.navto("Start Push","auto_"+($(this).closest("tr").index()-1))}));j.append($("<button>").text("Stop pushes").click(function(){if(confirm('Are you sure you want to stop all pushes matching \n"'+f[1]+" to "+f[2]+'"?'+(d.wait!=0?"\n\nRetrying is enabled. You'll probably want to set that to 0.": ++""))){var c=$(this);c.text("Stopping pushes..");var g=[],h;for(h in a.push_list)if(f[1]==a.push_list[h][1]&&f[2]==a.push_list[h][2]){g.push(a.push_list[h][0]);e.find("tr[data-pushid="+a.push_list[h][0]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}mist.send(function(){c.text("Stop pushes");b(g)},{push_stop:g,push_settings:{wait:0}})}}))}else{if(f.length>=6){var k=f[5];i.append($("<div>").append("Active for: "+UI.format.duration(k.active_seconds))).append($("<div>").append("Data transfered: "+ ++UI.format.bytes(k.bytes))).append($("<div>").append("Media time transfered: "+UI.format.duration(k.mediatime*0.001)));"pkt_retrans_count"in k&&i.append($("<div>").append("Packets retransmitted: "+UI.format.number(k.pkt_retrans_count||0)));"pkt_loss_count"in k&&i.append($("<div>").append("Packets lost: "+UI.format.number(k.pkt_loss_count||0)+" ("+UI.format.addUnit(UI.format.number(k.pkt_loss_perc||0),"%")+" over the last "+UI.format.addUnit(5,"s")+")"))}if(f.length>=5)for(var l in f[4]){k=f[4][l]; ++i.append($("<div>").append(UI.format.time(k[0])+" ["+k[1]+"] "+k[2]))}}return $("<tr>").css("vertical-align","top").attr("data-pushid",f[0]).append($("<td>").text(f[1])).append($("<td>").append(h.children())).append($("<td>").addClass("logs").append(i.children())).append(j)}K.html(UI.buildUI([{type:"help",help:"You can push streams to files or other servers, allowing them to broadcast your stream as well."}]));var d=a.push_settings;d||(d={});var e=$("<table>").append($("<tr>").append($("<th>").text("Stream")).append($("<th>").text("Target")).append($("<th>")).append($("<th>"))), ++f=e.clone();if("push_list"in a)for(var g in a.push_list)e.append(c(a.push_list[g],"Manual"));if("push_auto_list"in a)for(g in a.push_auto_list){var h=a.push_auto_list[g].slice();h.unshift(-1);f.append(c(h,"Automatic"))}K.append($("<h3>").text("Automatic pushes")).append(UI.buildUI([{label:"Delay before retry",unit:"s",type:"int",min:0,help:"How long the delay should be before MistServer retries an automatic push.<br>If set to 0, it does not retry.","default":0,pointer:{main:d,index:"wait"}},{label:"Maximum retries", ++unit:"/s",type:"int",min:0,help:"The maximum amount of retries per second (for all automatic pushes).<br>If set to 0, there is no limit.","default":0,pointer:{main:d,index:"maxspeed"}},{type:"buttons",buttons:[{type:"save",label:"Save","function":function(){mist.send(function(){UI.navto("Push")},{push_settings:d})}}]}])).append($("<button>").text("Add an automatic push").click(function(){UI.navto("Start Push","auto")}));f.find("tr").length==1?K.append($("<div>").text("No automatic pushes have been configured.").addClass("text").css("margin-top", ++"0.5em")):K.append(f);K.append($("<h3>").text("Pushes")).append($("<button>").text("Start a push").click(function(){UI.navto("Start Push")}));if(e.find("tr").length==1)K.append($("<div>").text("No pushes are active.").addClass("text").css("margin-top","0.5em"));else{var f=[],h=[],i=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any stream").val("")),j=$("<select>").css("margin-left","0.5em").append($("<option>").text("Any target").val(""));for(g in a.push_list){f.indexOf(a.push_list[g][1])== ++-1&&f.push(a.push_list[g][1]);h.indexOf(a.push_list[g][2])==-1&&h.push(a.push_list[g][2])}f.sort();h.sort();for(g in f)i.append($("<option>").text(f[g]));for(g in h)j.append($("<option>").text(h[g]));K.append($("<button>").text("Stop all pushes").click(function(){var c=[],d;for(d in a.push_list)c.push(a.push_list[d][0]);if(c.length!=0&&confirm("Are you sure you want to stop all pushes?")){mist.send(function(){b(c)},{push_stop:c});e.find("tr:not(:first-child)").html($("<td colspan=99>").append($("<span>").addClass("red").text("Stopping.."))); ++$(this).remove()}})).append($("<label>").css("margin-left","1em").append($("<span>").text("Stop all pushes that match: ").css("font-size","0.9em")).append(i).append($("<span>").css("margin-left","0.5em").text("and").css("font-size","0.9em")).append(j).append($("<button>").css("margin-left","0.5em").text("Apply").click(function(){var c=i.val(),d=j.val();if(c==""&&d=="")return alert("Looks like you want to stop all pushes. Maybe you should use that button?");var f={},g;for(g in a.push_list)if((c==""|| ++a.push_list[g][1]==c)&&(d==""||a.push_list[g][2]==d))f[a.push_list[g][0]]=a.push_list[g];if(Object.keys(f).length==0)return alert("No matching pushes.");c="Are you sure you want to stop these pushes?\n\n";for(g in f)c=c+(f[g][1]+" to "+f[g][2]+"\n");if(confirm(c)){f=Object.keys(f);mist.send(function(){b(f)},{push_stop:f});for(g in f)e.find("tr[data-pushid="+f[g]+"]").html($("<td colspan=99>").html($("<span>").addClass("red").text("Stopping..")))}}))).append(e)}UI.interval.set(function(){mist.send(function(a){var b= ++e.find("tr").first();e.empty();e.append(b);for(var d in a.push_list)e.append(c(a.push_list[d]))},{push_list:1})},5E3)},{push_settings:1,push_list:1,push_auto_list:1});break;case "Start Push":if(!("capabilities"in mist.data)){c.append("Loading Mist capabilities..");mist.send(function(){UI.navto("Start Push",b)},{capabilities:1});return}var x,ha=function(a){var d=false,f=b.split("_");b=f[0];f.length==2&&(d=f[1]);if(d!==false&&typeof a=="undefined")mist.send(function(a){ha(a.push_auto_list[d])},{push_auto_list:1}); ++else{var e=[],g={},h;for(h in mist.data.capabilities.connectors){f=mist.data.capabilities.connectors[h];if("push_urls"in f){e=e.concat(f.push_urls);g[h]=f.push_urls}}b=="auto"&&c.find("h2").text("Add automatic push");var i={params:{}};if(b=="auto"&&typeof a!="undefined"){i={stream:a[0],target:a[1],params:{}};f=i.target.split("?");if(f.length>1){params=f.pop();i.target=f.join("?");params=params.split("&");for(h in params){f=params[h].split("=");i.params[f.shift()]=f.join("=")}}}var j=$("<div>").css("margin", + "1em 0");h=[{label:"Stream name",type:"str",help:"This may either be a full stream name, a partial wildcard stream name, or a full wildcard stream name.<br>For example, given the stream <i>a</i> you can use: <ul> <li><i>a</i>: the stream configured as <i>a</i></li> <li><i>a+</i>: all streams configured as <i>a</i> with a wildcard behind it, but not <i>a</i> itself</li> <li><i>a+b</i>: only the version of stream <i>a</i> that has wildcard <i>b</i></li> </ul>", +-pointer:{main:i,index:"stream"},validate:["required",function(a){a=a.split("+");a=a[0];return a in mist.data.streams?false:{msg:"'"+a+"' is not a stream name.",classes:["orange"],"break":false}}],datalist:x,LTSonly:1},{label:"Target",type:"str",help:"Where the stream will be pushed to.<br> Valid formats: <ul> <li>"+e.join("</li><li>")+"</li> </ul> Valid text replacements: <ul> <li>$stream - inserts the stream name used to push to MistServer</li> <li>$day - inserts the current day number</li><li>$month - inserts the current month number</li> <li>$year - inserts the current year number</li><li>$hour - inserts the hour timestamp when stream was received</li> <li>$minute - inserts the minute timestamp the stream was received</li> <li>$seconds - inserts the seconds timestamp when the stream was received</li> <li>$datetime - inserts $year.$month.$day.$hour.$minute.$seconds timestamp when the stream was received</li> </ul> Valid URL parameters: <ul> <li>recstart=123 - media timestamp in milisseconds where the push should start</li> <li>recstop=456 - media timestamp in miliseconds where the push should stop</li> <li>recstartunix=150000000 - unix time in seconds where the push should start. This will override the recstart parameter.</li> <li>recstopunix=150000000 - unix time in seconds where the push should stop. This will override the recstop parameter.</li> </ul>", +-pointer:{main:i,index:"target"},validate:["required",function(a){for(var b in e)if(mist.inputMatch(e[b],a))return false;return{msg:"Does not match a valid target.<br>Valid formats:<ul><li>"+e.join("</li><li>")+"</li></ul>",classes:["red"]}}],"function":function(){var a=false;for(connector in f)for(var b in f[connector])if(mist.inputMatch(f[connector][b],$(this).getval())){a=connector;break}if(a){j.html($("<h3>").text(mist.data.capabilities.connectors[a].friendly));j.append(UI.buildUI(mist.convertBuildOptions({desc:mist.data.capabilities.connectors[a].desc, +-optional:mist.data.capabilities.connectors[a].push_parameters},i.params)))}else j.html($("<h4>").addClass("red").text("Unrecognized target.")).append($("<span>").text("Please edit the push target."))},LTSonly:1},j];h.push({type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Push")}},{type:"save",label:"Save","function":function(){var c=i.params,d;for(d in c)c[d]===null&&delete c[d];if(Object.keys(c).length){var g="?",e=i.target.split("?");if(e.length>1){g="&";e=e[e.length- +-1];e=e.split("&");for(d in e){var f=e[d].split("=")[0];f in c&&delete c[f]}}if(Object.keys(c).length){e=[];for(d in c)e.push(d+"="+c[d]);g=g+e.join("&");i.target=i.target+g}}c={};c[b=="auto"?"push_auto_add":"push_start"]=i;if(typeof a!="undefined"&&(a[0]!=i.stream||a[1]!=i.target))c.push_auto_remove=[a];mist.send(function(){UI.navto("Push")},c)}}]});c.append(UI.buildUI(h))}};mist.data.LTS?mist.send(function(a){(x=a.active_streams)||(x=[]);var a=[],b;for(b in x)x[b].indexOf("+")!=-1&&a.push(x[b].replace(/\+.*/, +-"")+"+");x=x.concat(a);var c=0,d=0;for(b in mist.data.streams){x.push(b);if(mist.inputMatch(UI.findInput("Folder").source_match,mist.data.streams[b].source)){x.push(b+"+");mist.send(function(a,b){var g=b.stream,e;for(e in a.browse.files)for(var f in mist.data.capabilities.inputs)f.indexOf("Buffer")>=0||(f.indexOf("Folder")>=0||f.indexOf("Buffer.exe")>=0||f.indexOf("Folder.exe")>=0)||mist.inputMatch(mist.data.capabilities.inputs[f].source_match,"/"+a.browse.files[e])&&x.push(g+"+"+a.browse.files[e]); +-d++;if(c==d){x=x.filter(function(a,b,c){return c.lastIndexOf(a)===b}).sort();ia()}},{browse:mist.data.streams[b].source},{stream:b});c++}}if(c==d){x=x.filter(function(a,b,c){return c.lastIndexOf(a)===b}).sort();ia()}},{active_streams:1}):(x=Object.keys(mist.data.streams),ia());break;case "Triggers":if(!("triggers"in mist.data.config)||!mist.data.config.triggers)mist.data.config.triggers={};var C=$("<tbody>"),Ua=$("<table>").html($("<thead>").html($("<tr>").html($("<th>").text("Trigger on").attr("data-sort-type", +-"string").addClass("sorting-asc")).append($("<th>").text("Applies to").attr("data-sort-type","string")).append($("<th>").text("Handler").attr("data-sort-type","string")).append($("<th>")))).append(C);c.append(UI.buildUI([{type:"help",help:"Triggers are a way to react to events that occur inside MistServer. These allow you to block specific users, redirect streams, keep tabs on what is being pushed where, etcetera. For full documentation, please refer to the developer documentation section on the MistServer website."}])).append($("<button>").text("New trigger").click(function(){UI.navto("Edit Trigger")})).append(Ua); +-Ua.stupidtable();var ta=mist.data.config.triggers;for(r in ta)for(var Va in ta[r]){var ua=triggerRewrite(ta[r][Va]);C.append($("<tr>").attr("data-index",r+","+Va).append($("<td>").text(r)).append($("<td>").text("streams"in ua?ua.streams.join(", "):"")).append($("<td>").text(ua.handler)).append($("<td>").html($("<button>").text("Edit").click(function(){UI.navto("Edit Trigger",$(this).closest("tr").attr("data-index"))})).append($("<button>").text("Delete").click(function(){var a=$(this).closest("tr").attr("data-index").split(","); ++pointer:{main:i,index:"stream"},validate:["required",function(a){a=a.split("+");a=a[0];return a in mist.data.streams?false:{msg:"'"+a+"' is not a stream name.",classes:["orange"],"break":false}}],datalist:x},{label:"Target",type:"str",help:"Where the stream will be pushed to.<br> Valid formats: <ul> <li>"+e.join("</li><li>")+"</li> </ul> Valid text replacements: <ul> <li>$stream - inserts the stream name used to push to MistServer</li> <li>$day - inserts the current day number</li><li>$month - inserts the current month number</li> <li>$year - inserts the current year number</li><li>$hour - inserts the hour timestamp when stream was received</li> <li>$minute - inserts the minute timestamp the stream was received</li> <li>$seconds - inserts the seconds timestamp when the stream was received</li> <li>$datetime - inserts $year.$month.$day.$hour.$minute.$seconds timestamp when the stream was received</li> </ul> Valid URL parameters: <ul> <li>recstart=123 - media timestamp in milisseconds where the push should start</li> <li>recstop=456 - media timestamp in miliseconds where the push should stop</li> <li>recstartunix=150000000 - unix time in seconds where the push should start. This will override the recstart parameter.</li> <li>recstopunix=150000000 - unix time in seconds where the push should stop. This will override the recstop parameter.</li> </ul>", ++pointer:{main:i,index:"target"},validate:["required",function(a){for(var b in e)if(mist.inputMatch(e[b],a))return false;return{msg:"Does not match a valid target.<br>Valid formats:<ul><li>"+e.join("</li><li>")+"</li></ul>",classes:["red"]}}],"function":function(){var a=false;for(connector in g)for(var b in g[connector])if(mist.inputMatch(g[connector][b],$(this).getval())){a=connector;break}if(a){j.html($("<h3>").text(mist.data.capabilities.connectors[a].friendly));j.append(UI.buildUI(mist.convertBuildOptions({desc:mist.data.capabilities.connectors[a].desc, ++optional:mist.data.capabilities.connectors[a].push_parameters},i.params)))}else j.html($("<h4>").addClass("red").text("Unrecognized target.")).append($("<span>").text("Please edit the push target."))}},j];h.push({type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Push")}},{type:"save",label:"Save","function":function(){var c=i.params,d;for(d in c)c[d]===null&&delete c[d];if(Object.keys(c).length){var f="?",e=i.target.split("?");if(e.length>1){f="&";e=e[e.length- ++1];e=e.split("&");for(d in e){var g=e[d].split("=")[0];g in c&&delete c[g]}}if(Object.keys(c).length){e=[];for(d in c)e.push(d+"="+c[d]);f=f+e.join("&");i.target=i.target+f}}c={};c[b=="auto"?"push_auto_add":"push_start"]=i;if(typeof a!="undefined"&&(a[0]!=i.stream||a[1]!=i.target))c.push_auto_remove=[a];mist.send(function(){UI.navto("Push")},c)}}]});c.append(UI.buildUI(h))}};mist.data.LTS?mist.send(function(a){(x=a.active_streams)||(x=[]);var a=[],b;for(b in x)x[b].indexOf("+")!=-1&&a.push(x[b].replace(/\+.*/, ++"")+"+");x=x.concat(a);var c=0,d=0;for(b in mist.data.streams){x.push(b);if(mist.inputMatch(UI.findInput("Folder").source_match,mist.data.streams[b].source)){x.push(b+"+");mist.send(function(a,b){var f=b.stream,e;for(e in a.browse.files)for(var g in mist.data.capabilities.inputs)g.indexOf("Buffer")>=0||(g.indexOf("Folder")>=0||g.indexOf("Buffer.exe")>=0||g.indexOf("Folder.exe")>=0)||mist.inputMatch(mist.data.capabilities.inputs[g].source_match,"/"+a.browse.files[e])&&x.push(f+"+"+a.browse.files[e]); ++d++;if(c==d){x=x.filter(function(a,b,c){return c.lastIndexOf(a)===b}).sort();ha()}},{browse:mist.data.streams[b].source},{stream:b});c++}}if(c==d){x=x.filter(function(a,b,c){return c.lastIndexOf(a)===b}).sort();ha()}},{active_streams:1}):(x=Object.keys(mist.data.streams),ha());break;case "Triggers":if(!("triggers"in mist.data.config)||!mist.data.config.triggers)mist.data.config.triggers={};var D=$("<tbody>"),Ua=$("<table>").html($("<thead>").html($("<tr>").html($("<th>").text("Trigger on").attr("data-sort-type", ++"string").addClass("sorting-asc")).append($("<th>").text("Applies to").attr("data-sort-type","string")).append($("<th>").text("Handler").attr("data-sort-type","string")).append($("<th>")))).append(D);c.append(UI.buildUI([{type:"help",help:"Triggers are a way to react to events that occur inside MistServer. These allow you to block specific users, redirect streams, keep tabs on what is being pushed where, etcetera. For full documentation, please refer to the developer documentation section on the MistServer website."}])).append($("<button>").text("New trigger").click(function(){UI.navto("Edit Trigger")})).append(Ua); ++Ua.stupidtable();var sa=mist.data.config.triggers;for(r in sa)for(var Va in sa[r]){var ta=triggerRewrite(sa[r][Va]);D.append($("<tr>").attr("data-index",r+","+Va).append($("<td>").text(r)).append($("<td>").text("streams"in ta?ta.streams.join(", "):"")).append($("<td>").text(ta.handler)).append($("<td>").html($("<button>").text("Edit").click(function(){UI.navto("Edit Trigger",$(this).closest("tr").attr("data-index"))})).append($("<button>").text("Delete").click(function(){var a=$(this).closest("tr").attr("data-index").split(","); + if(confirm("Are you sure you want to delete this "+a[0]+" trigger?")){mist.data.config.triggers[a[0]].splice(a[1],1);mist.data.config.triggers[a[0]].length==0&&delete mist.data.config.triggers[a[0]];mist.send(function(){UI.navto("Triggers")},{config:mist.data.config})}}))))}break;case "Edit Trigger":if(!("triggers"in mist.data.config)||!mist.data.config.triggers)mist.data.config.triggers={};if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});c.append("Loading.."); +-return}if(b)var b=b.split(","),ba=triggerRewrite(mist.data.config.triggers[b[0]][b[1]]),p={triggeron:b[0],appliesto:ba.streams,url:ba.handler,async:ba.sync,"default":ba["default"],params:ba.params};else c.html($("<h2>").text("New Trigger")),p={};var Wa=[];for(r in mist.data.capabilities.triggers)Wa.push([r,r+": "+mist.data.capabilities.triggers[r].when]);var va=$("<div>").addClass("desc"),Xa=$("<div>");c.append(UI.buildUI([{label:"Trigger on",pointer:{main:p,index:"triggeron"},help:"For what event this trigger should activate.", +-type:"select",select:Wa,LTSonly:!0,validate:["required"],"function":function(){var a=$(this).getval(),b=mist.data.capabilities.triggers[a];va.html("");if(b){a=[$("<h4>").text("Trigger properties"),{type:"help",help:'The trigger "<i>'+a+'</i>" has the following properties:'},{type:"span",label:"Triggers",value:b.when,help:"When this trigger is activated"}];b.payload!=""&&a.push({label:"Payload",type:"textarea",value:b.payload,rows:b.payload.split("\n").length,readonly:true,clipboard:true,help:"The information this trigger sends to the handler."}); ++return}if(b)var b=b.split(","),aa=triggerRewrite(mist.data.config.triggers[b[0]][b[1]]),p={triggeron:b[0],appliesto:aa.streams,url:aa.handler,async:aa.sync,"default":aa["default"],params:aa.params};else c.html($("<h2>").text("New Trigger")),p={};var Wa=[];for(r in mist.data.capabilities.triggers)Wa.push([r,r+": "+mist.data.capabilities.triggers[r].when]);var ua=$("<div>").addClass("desc"),Xa=$("<div>");c.append(UI.buildUI([{label:"Trigger on",pointer:{main:p,index:"triggeron"},help:"For what event this trigger should activate.", ++type:"select",select:Wa,validate:["required"],"function":function(){var a=$(this).getval(),b=mist.data.capabilities.triggers[a];ua.html("");if(b){a=[$("<h4>").text("Trigger properties"),{type:"help",help:'The trigger "<i>'+a+'</i>" has the following properties:'},{type:"span",label:"Triggers",value:b.when,help:"When this trigger is activated"}];b.payload!=""&&a.push({label:"Payload",type:"textarea",value:b.payload,rows:b.payload.split("\n").length,readonly:true,clipboard:true,help:"The information this trigger sends to the handler."}); + a.push({type:"span",label:"Requires response",value:function(a){switch(a){case "ignored":return"No. The trigger will ignore the response of the handler.";case "always":return"Yes. The trigger needs a response to proceed.";case "when-blocking":return"The trigger needs a response to proceed if it is configured to be blocking.";default:return a}}(b.response),help:"Whether this trigger requires a response from the trigger handler"});a.push({type:"span",label:"Response action",value:b.response_action, +-help:"What this trigger will do with its handler's response"});va.append(UI.buildUI(a));b.stream_specific?$("[name=appliesto]").closest(".UIelement").show():$("[name=appliesto]").setval([]).closest(".UIelement").hide();if(b.argument){$("[name=params]").closest(".UIelement").show();Xa.text(b.argument)}else $("[name=params]").setval("").closest(".UIelement").hide()}}},va,$("<h4>").text("Trigger settings"),{label:"Applies to",pointer:{main:p,index:"appliesto"},help:"For triggers that can apply to specific streams, this value decides what streams they are triggered for. (none checked = always triggered)", +-type:"checklist",checklist:Object.keys(mist.data.streams),LTSonly:!0},$("<br>"),{label:"Handler (URL or executable)",help:"This can be either an HTTP URL or a full path to an executable.",pointer:{main:p,index:"url"},validate:["required"],type:"str",LTSonly:!0},{label:"Blocking",type:"checkbox",help:"If checked, pauses processing and uses the response of the handler. If the response does not start with 1, true, yes or cont, further processing is aborted. If unchecked, processing is never paused and the response is not checked.", +-pointer:{main:p,index:"async"},LTSonly:!0},{label:"Parameters",type:"str",help:$("<div>").text("The extra data you want this trigger to use.").append(Xa),pointer:{main:p,index:"params"},LTSonly:!0},{label:"Default response",type:"str",help:"The default response in case the handler fails or is set to non-blocking.",placeholder:"true",pointer:{main:p,index:"default"},LTSonly:!0},{type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Triggers")}},{type:"save",label:"Save", +-"function":function(){b&&mist.data.config.triggers[b[0]].splice(b[1],1);var a={handler:p.url,sync:p.async?true:false,streams:typeof p.appliesto=="undefined"?[]:p.appliesto,params:p.params,"default":p["default"]};if(!("triggers"in mist.data.config))mist.data.config.triggers={};p.triggeron in mist.data.config.triggers||(mist.data.config.triggers[p.triggeron]=[]);mist.data.config.triggers[p.triggeron].push(a);mist.send(function(){UI.navto("Triggers")},{config:mist.data.config})}}]}]));$("[name=triggeron]").trigger("change"); +-break;case "Logs":var Ya=$("<button>").text("Refresh now").click(function(){$(this).text("Loading..");mist.send(function(){wa();Ya.text("Refresh now")})}).css("padding","0.2em 0.5em").css("flex-grow",0);c.append(UI.buildUI([{type:"help",help:"Here you have an overview of all edited settings within MistServer and possible warnings or errors MistServer has encountered. MistServer stores up to 100 logs at a time."},{label:"Refresh every",type:"select",select:[[10,"10 seconds"],[30,"30 seconds"],[60, +-"minute"],[300,"5 minutes"]],value:30,"function":function(){UI.interval.clear();UI.interval.set(function(){mist.send(function(){wa()})},$(this).val()*1E3)},help:"How often the table below should be updated."},{label:"..or",type:"DOMfield",DOMfield:Ya,help:"Instantly refresh the table below."}]));c.append($("<button>").text("Purge logs").click(function(){mist.send(function(){mist.data.log=[];UI.navto("Logs")},{clearstatlogs:true})}));C=$("<tbody>").css("font-size","0.9em");c.append($("<table>").addClass("logs").append(C)); +-var bb=function(a){var b=$("<span>").text(a);switch(a){case "WARN":b.addClass("orange");break;case "ERROR":case "FAIL":b.addClass("red")}return b},wa=function(){var a=mist.data.log;if(a){a.length>=2&&a[0][0]<a[a.length-1][0]&&a.reverse();C.html("");for(var b in a){var c=$("<span>").addClass("content"),d=a[b][2].split("|"),g;for(g in d)c.append($("<span>").text(d[g]));C.append($("<tr>").html($("<td>").text(UI.format.dateTime(a[b][0],"long")).css("white-space","nowrap")).append($("<td>").html(bb(a[b][1])).css("text-align", +-"center")).append($("<td>").html(c).css("text-align","left")))}}};wa();break;case "Statistics":var D=$("<span>").text("Loading..");c.append(D);var p={graph:"new"},z=mist.stored.get().graphs?$.extend(!0,{},mist.stored.get().graphs):{},ca={};for(r in mist.data.streams)ca[r]=!0;for(r in mist.data.active_streams)ca[mist.data.active_streams[r]]=!0;var ca=Object.keys(ca).sort(),xa=[];for(r in mist.data.config.protocols)xa.push(mist.data.config.protocols[r].connector);xa.sort();mist.send(function(){UI.plot.datatype.templates.cpuload.cores= +-0;for(var a in mist.data.capabilities.cpu)UI.plot.datatype.templates.cpuload.cores=UI.plot.datatype.templates.cpuload.cores+mist.data.capabilities.cpu[a].cores;D.html(UI.buildUI([{type:"help",help:"Here you will find the MistServer stream statistics, you can select various categories yourself. All statistics are live: up to five minutes are saved."},$("<h3>").text("Select the data to display"),{label:"Add to",type:"select",select:[["new","New graph"]],pointer:{main:p,index:"graph"},classes:["graph_ids"], +-"function":function(){if($(this).val()){var a=D.find(".graph_xaxis"),b=D.find(".graph_id");if($(this).val()=="new"){a.children("option").prop("disabled",false);b.setval("Graph "+(Object.keys(z).length+1)).closest("label").show()}else{var c=z[$(this).val()].xaxis;a.children("option").prop("disabled",true).filter('[value="'+c+'"]').prop("disabled",false);b.closest("label").hide()}a.children('option[value="'+a.val()+'"]:disabled').length&&a.val(a.children("option:enabled").first().val());a.trigger("change")}}}, +-{label:"Graph id",type:"str",pointer:{main:p,index:"id"},classes:["graph_id"],validate:[function(a){return a in z?{msg:"This graph id has already been used. Please enter something else.",classes:["red"]}:false}]},{label:"Axis type",type:"select",select:[["time","Time line"]],pointer:{main:p,index:"xaxis"},value:"time",classes:["graph_xaxis"],"function":function(){$s=D.find(".graph_datatype");switch($(this).getval()){case "coords":$s.children("option").prop("disabled",true).filter('[value="coords"]').prop("disabled", +-false);break;case "time":$s.children("option").prop("disabled",false).filter('[value="coords"]').prop("disabled",true)}if(!$s.val()||$s.children('option[value="'+$s.val()+'"]:disabled').length){$s.val($s.children("option:enabled").first().val());$s.trigger("change")}}},{label:"Data type",type:"select",select:[["clients","Connections"],["upbps","Bandwidth (up)"],["downbps","Bandwidth (down)"],["cpuload","CPU use"],["memload","Memory load"],["coords","Client location"],["perc_lost","Lost packages"], +-["perc_retrans","Re-transmitted packages"]],pointer:{main:p,index:"datatype"},classes:["graph_datatype"],"function":function(){$s=D.find(".graph_origin");switch($(this).getval()){case "cpuload":case "memload":$s.find("input[type=radio]").not('[value="total"]').prop("disabled",true);$s.find('input[type=radio][value="total"]').prop("checked",true);break;default:$s.find("input[type=radio]").prop("disabled",false)}}},{label:"Data origin",type:"radioselect",radioselect:[["total","All"],["stream","The stream:", +-ca],["protocol","The protocol:",xa]],pointer:{main:p,index:"origin"},value:["total"],classes:["graph_origin"]},{type:"buttons",buttons:[{label:"Add data set",type:"save","function":function(){var a;if(p.graph=="new"){a=UI.plot.addGraph(p,b);z[a.id]=a;D.find("input.graph_id").val("");D.find("select.graph_ids").append($("<option>").text(a.id)).val(a.id).trigger("change")}else a=z[p.graph];var c=UI.plot.datatype.getOptions({datatype:p.datatype,origin:p.origin});a.datasets.push(c);UI.plot.save(a);UI.plot.go(z)}}]}])); +-var b=$("<div>").addClass("graph_container");c.append(b);var d=D.find("select.graph_ids");for(a in z){var g=UI.plot.addGraph(z[a],b);d.append($("<option>").text(g.id)).val(g.id);var e=[],f;for(f in z[a].datasets){var h=UI.plot.datatype.getOptions({datatype:z[a].datasets[f].datatype,origin:z[a].datasets[f].origin});e.push(h)}g.datasets=e;z[g.id]=g}d.trigger("change");UI.plot.go(z);UI.interval.set(function(){UI.plot.go(z)},1E4)},{active_streams:!0,capabilities:!0});break;case "Server Stats":if("undefined"== +-typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});c.append("Loading..");return}var ya=$("<table>"),L=$("<table>"),Za={vheader:"CPUs",labels:["Model","Processor speed","Amount of cores","Amount of threads"],content:[]};for(r in mist.data.capabilities.cpu){var ja=mist.data.capabilities.cpu[r];Za.content.push({header:"CPU #"+(Number(r)+1),body:[ja.model,UI.format.addUnit(UI.format.number(ja.mhz),"MHz"),ja.cores,ja.threads]})}var cb=UI.buildVheaderTable(Za),$a=function(){var a= +-mist.data.capabilities.mem,b=mist.data.capabilities.load,a={vheader:"Memory",labels:["Used","Cached","Available","Total"],content:[{header:"Physical memory",body:[UI.format.bytes(a.used*1048576)+" ("+UI.format.addUnit(b.memory,"%")+")",UI.format.bytes(a.cached*1048576),UI.format.bytes(a.free*1048576),UI.format.bytes(a.total*1048576)]},{header:"Swap memory",body:[UI.format.bytes((a.swaptotal-a.swapfree)*1048576),UI.format.addUnit("","N/A"),UI.format.bytes(a.swapfree*1048576),UI.format.bytes(a.swaptotal* +-1048576)]}]},a=UI.buildVheaderTable(a);ya.replaceWith(a);ya=a;b={vheader:"Load average",labels:["CPU use","1 minute","5 minutes","15 minutes"],content:[{header:" ",body:[UI.format.addUnit(UI.format.number(mist.data.capabilities.cpu_use/10),"%"),UI.format.number(b.one/100),UI.format.number(b.five/100),UI.format.number(b.fifteen/100)]}]};b=UI.buildVheaderTable(b);L.replaceWith(b);L=b};$a();c.append(UI.buildUI([{type:"help",help:"You can find general server statistics here. Note that memory and CPU usage is for your entire machine, not just MistServer."}])).append($("<table>").css("width", +-"auto").addClass("nolay").append($("<tr>").append($("<td>").append(ya)).append($("<td>").append(L))).append($("<tr>").append($("<td>").append(cb).attr("colspan",2))));UI.interval.set(function(){mist.send(function(){$a()},{capabilities:true})},3E4);break;case "Email for Help":var E=$.extend({},mist.data);delete E.statistics;delete E.totals;delete E.clients;delete E.capabilities;E=JSON.stringify(E);E="Version: "+mist.data.config.version+"\n\nConfig:\n"+E;p={};c.append(UI.buildUI([{type:"help",help:"You can use this form to email MistServer support if you're having difficulties.<br>A copy of your server config file will automatically be included."}, +-{type:"str",label:"Your name",validate:["required"],pointer:{main:p,index:"name"},value:mist.user.name},{type:"email",label:"Your email address",validate:["required"],pointer:{main:p,index:"email"}},{type:"hidden",value:"Integrated Help",pointer:{main:p,index:"subject"}},{type:"hidden",value:"-",pointer:{main:p,index:"company"}},{type:"textarea",rows:20,label:"Your message",validate:["required"],pointer:{main:p,index:"message"}},{type:"textarea",rows:20,label:"Your config file",readonly:!0,value:E, +-pointer:{main:p,index:"configfile"}},{type:"buttons",buttons:[{type:"save",label:"Send","function":function(a){$(a).text("Sending..");$.ajax({type:"POST",url:"https://mistserver.org/contact?skin=plain",data:p,success:function(a){a=$("<span>").html(a);a.find("script").remove();c.html(a[0].innerHTML)}})}}]}]));break;case "Disconnect":mist.user.password="";delete mist.user.authstring;delete mist.user.loggedin;sessionStorage.removeItem("mistLogin");UI.navto("Login");break;default:c.append($("<p>").text("This tab does not exist."))}c.find(".field").filter(function(){var a= +-$(this).getval();return a==""||a==null?true:false}).each(function(){var a=[];$(this).is("input, select, textarea")?a.push($(this)):a=$(this).find("input, select, textarea");if(a.length){$(a[0]).focus();return false}})}};"origin"in location||(location.origin=location.protocol+"//");var host;host="file://"==location.origin?"http://localhost:4242/api":location.origin+location.pathname.replace(/\/+$/,"")+"/api"; ++help:"What this trigger will do with its handler's response"});ua.append(UI.buildUI(a));b.stream_specific?$("[name=appliesto]").closest(".UIelement").show():$("[name=appliesto]").setval([]).closest(".UIelement").hide();if(b.argument){$("[name=params]").closest(".UIelement").show();Xa.text(b.argument)}else $("[name=params]").setval("").closest(".UIelement").hide()}}},ua,$("<h4>").text("Trigger settings"),{label:"Applies to",pointer:{main:p,index:"appliesto"},help:"For triggers that can apply to specific streams, this value decides what streams they are triggered for. (none checked = always triggered)", ++type:"checklist",checklist:Object.keys(mist.data.streams)},$("<br>"),{label:"Handler (URL or executable)",help:"This can be either an HTTP URL or a full path to an executable.",pointer:{main:p,index:"url"},validate:["required"],type:"str"},{label:"Blocking",type:"checkbox",help:"If checked, pauses processing and uses the response of the handler. If the response does not start with 1, true, yes or cont, further processing is aborted. If unchecked, processing is never paused and the response is not checked.", ++pointer:{main:p,index:"async"}},{label:"Parameters",type:"str",help:$("<div>").text("The extra data you want this trigger to use.").append(Xa),pointer:{main:p,index:"params"}},{label:"Default response",type:"str",help:"The default response in case the handler fails or is set to non-blocking.",placeholder:"true",pointer:{main:p,index:"default"}},{type:"buttons",buttons:[{type:"cancel",label:"Cancel","function":function(){UI.navto("Triggers")}},{type:"save",label:"Save","function":function(){b&&mist.data.config.triggers[b[0]].splice(b[1], ++1);var a={handler:p.url,sync:p.async?true:false,streams:typeof p.appliesto=="undefined"?[]:p.appliesto,params:p.params,"default":p["default"]};if(!("triggers"in mist.data.config))mist.data.config.triggers={};p.triggeron in mist.data.config.triggers||(mist.data.config.triggers[p.triggeron]=[]);mist.data.config.triggers[p.triggeron].push(a);mist.send(function(){UI.navto("Triggers")},{config:mist.data.config})}}]}]));$("[name=triggeron]").trigger("change");break;case "Logs":var Ya=$("<button>").text("Refresh now").click(function(){$(this).text("Loading.."); ++mist.send(function(){va();Ya.text("Refresh now")})}).css("padding","0.2em 0.5em").css("flex-grow",0);c.append(UI.buildUI([{type:"help",help:"Here you have an overview of all edited settings within MistServer and possible warnings or errors MistServer has encountered. MistServer stores up to 100 logs at a time."},{label:"Refresh every",type:"select",select:[[10,"10 seconds"],[30,"30 seconds"],[60,"minute"],[300,"5 minutes"]],value:30,"function":function(){UI.interval.clear();UI.interval.set(function(){mist.send(function(){va()})}, ++$(this).val()*1E3)},help:"How often the table below should be updated."},{label:"..or",type:"DOMfield",DOMfield:Ya,help:"Instantly refresh the table below."}]));c.append($("<button>").text("Purge logs").click(function(){mist.send(function(){mist.data.log=[];UI.navto("Logs")},{clearstatlogs:true})}));D=$("<tbody>").css("font-size","0.9em");c.append($("<table>").addClass("logs").append(D));var bb=function(a){var b=$("<span>").text(a);switch(a){case "WARN":b.addClass("orange");break;case "ERROR":case "FAIL":b.addClass("red")}return b}, ++va=function(){var a=mist.data.log;if(a){a.length>=2&&a[0][0]<a[a.length-1][0]&&a.reverse();D.html("");for(var b in a){var c=$("<span>").addClass("content"),d=a[b][2].split("|"),f;for(f in d)c.append($("<span>").text(d[f]));D.append($("<tr>").html($("<td>").text(UI.format.dateTime(a[b][0],"long")).css("white-space","nowrap")).append($("<td>").html(bb(a[b][1])).css("text-align","center")).append($("<td>").html(c).css("text-align","left")))}}};va();break;case "Statistics":var G=$("<span>").text("Loading.."); ++c.append(G);var p={graph:"new"},z=mist.stored.get().graphs?$.extend(!0,{},mist.stored.get().graphs):{},ba={};for(r in mist.data.streams)ba[r]=!0;for(r in mist.data.active_streams)ba[mist.data.active_streams[r]]=!0;var ba=Object.keys(ba).sort(),wa=[];for(r in mist.data.config.protocols)wa.push(mist.data.config.protocols[r].connector);wa.sort();mist.send(function(){UI.plot.datatype.templates.cpuload.cores=0;for(var a in mist.data.capabilities.cpu)UI.plot.datatype.templates.cpuload.cores=UI.plot.datatype.templates.cpuload.cores+ ++mist.data.capabilities.cpu[a].cores;G.html(UI.buildUI([{type:"help",help:"Here you will find the MistServer stream statistics, you can select various categories yourself. All statistics are live: up to five minutes are saved."},$("<h3>").text("Select the data to display"),{label:"Add to",type:"select",select:[["new","New graph"]],pointer:{main:p,index:"graph"},classes:["graph_ids"],"function":function(){if($(this).val()){var a=G.find(".graph_xaxis"),b=G.find(".graph_id");if($(this).val()=="new"){a.children("option").prop("disabled", ++false);b.setval("Graph "+(Object.keys(z).length+1)).closest("label").show()}else{var c=z[$(this).val()].xaxis;a.children("option").prop("disabled",true).filter('[value="'+c+'"]').prop("disabled",false);b.closest("label").hide()}a.children('option[value="'+a.val()+'"]:disabled').length&&a.val(a.children("option:enabled").first().val());a.trigger("change")}}},{label:"Graph id",type:"str",pointer:{main:p,index:"id"},classes:["graph_id"],validate:[function(a){return a in z?{msg:"This graph id has already been used. Please enter something else.", ++classes:["red"]}:false}]},{label:"Axis type",type:"select",select:[["time","Time line"]],pointer:{main:p,index:"xaxis"},value:"time",classes:["graph_xaxis"],"function":function(){$s=G.find(".graph_datatype");switch($(this).getval()){case "coords":$s.children("option").prop("disabled",true).filter('[value="coords"]').prop("disabled",false);break;case "time":$s.children("option").prop("disabled",false).filter('[value="coords"]').prop("disabled",true)}if(!$s.val()||$s.children('option[value="'+$s.val()+ ++'"]:disabled').length){$s.val($s.children("option:enabled").first().val());$s.trigger("change")}}},{label:"Data type",type:"select",select:[["clients","Connections"],["upbps","Bandwidth (up)"],["downbps","Bandwidth (down)"],["cpuload","CPU use"],["memload","Memory load"],["coords","Client location"],["perc_lost","Lost packages"],["perc_retrans","Re-transmitted packages"]],pointer:{main:p,index:"datatype"},classes:["graph_datatype"],"function":function(){$s=G.find(".graph_origin");switch($(this).getval()){case "cpuload":case "memload":$s.find("input[type=radio]").not('[value="total"]').prop("disabled", ++true);$s.find('input[type=radio][value="total"]').prop("checked",true);break;default:$s.find("input[type=radio]").prop("disabled",false)}}},{label:"Data origin",type:"radioselect",radioselect:[["total","All"],["stream","The stream:",ba],["protocol","The protocol:",wa]],pointer:{main:p,index:"origin"},value:["total"],classes:["graph_origin"]},{type:"buttons",buttons:[{label:"Add data set",type:"save","function":function(){var a;if(p.graph=="new"){a=UI.plot.addGraph(p,b);z[a.id]=a;G.find("input.graph_id").val(""); ++G.find("select.graph_ids").append($("<option>").text(a.id)).val(a.id).trigger("change")}else a=z[p.graph];var c=UI.plot.datatype.getOptions({datatype:p.datatype,origin:p.origin});a.datasets.push(c);UI.plot.save(a);UI.plot.go(z)}}]}]));var b=$("<div>").addClass("graph_container");c.append(b);var d=G.find("select.graph_ids");for(a in z){var f=UI.plot.addGraph(z[a],b);d.append($("<option>").text(f.id)).val(f.id);var e=[],g;for(g in z[a].datasets){var h=UI.plot.datatype.getOptions({datatype:z[a].datasets[g].datatype, ++origin:z[a].datasets[g].origin});e.push(h)}f.datasets=e;z[f.id]=f}d.trigger("change");UI.plot.go(z);UI.interval.set(function(){UI.plot.go(z)},1E4)},{active_streams:!0,capabilities:!0});break;case "Server Stats":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});c.append("Loading..");return}var xa=$("<table>"),M=$("<table>"),Za={vheader:"CPUs",labels:["Model","Processor speed","Amount of cores","Amount of threads"],content:[]};for(r in mist.data.capabilities.cpu){var ia= ++mist.data.capabilities.cpu[r];Za.content.push({header:"CPU #"+(Number(r)+1),body:[ia.model,UI.format.addUnit(UI.format.number(ia.mhz),"MHz"),ia.cores,ia.threads]})}var cb=UI.buildVheaderTable(Za),$a=function(){var a=mist.data.capabilities.mem,b=mist.data.capabilities.load,a={vheader:"Memory",labels:["Used","Cached","Available","Total"],content:[{header:"Physical memory",body:[UI.format.bytes(a.used*1048576)+" ("+UI.format.addUnit(b.memory,"%")+")",UI.format.bytes(a.cached*1048576),UI.format.bytes(a.free* ++1048576),UI.format.bytes(a.total*1048576)]},{header:"Swap memory",body:[UI.format.bytes((a.swaptotal-a.swapfree)*1048576),UI.format.addUnit("","N/A"),UI.format.bytes(a.swapfree*1048576),UI.format.bytes(a.swaptotal*1048576)]}]},a=UI.buildVheaderTable(a);xa.replaceWith(a);xa=a;b={vheader:"Load average",labels:["CPU use","1 minute","5 minutes","15 minutes"],content:[{header:" ",body:[UI.format.addUnit(UI.format.number(mist.data.capabilities.cpu_use/10),"%"),UI.format.number(b.one/100),UI.format.number(b.five/ ++100),UI.format.number(b.fifteen/100)]}]};b=UI.buildVheaderTable(b);M.replaceWith(b);M=b};$a();c.append(UI.buildUI([{type:"help",help:"You can find general server statistics here. Note that memory and CPU usage is for your entire machine, not just MistServer."}])).append($("<table>").css("width","auto").addClass("nolay").append($("<tr>").append($("<td>").append(xa)).append($("<td>").append(M))).append($("<tr>").append($("<td>").append(cb).attr("colspan",2))));UI.interval.set(function(){mist.send(function(){$a()}, ++{capabilities:true})},3E4);break;case "Email for Help":var H=$.extend({},mist.data);delete H.statistics;delete H.totals;delete H.clients;delete H.capabilities;H=JSON.stringify(H);H="Version: "+mist.data.config.version+"\n\nConfig:\n"+H;p={};c.append(UI.buildUI([{type:"help",help:"You can use this form to email MistServer support if you're having difficulties.<br>A copy of your server config file will automatically be included."},{type:"str",label:"Your name",validate:["required"],pointer:{main:p, ++index:"name"},value:mist.user.name},{type:"email",label:"Your email address",validate:["required"],pointer:{main:p,index:"email"}},{type:"hidden",value:"Integrated Help",pointer:{main:p,index:"subject"}},{type:"hidden",value:"-",pointer:{main:p,index:"company"}},{type:"textarea",rows:20,label:"Your message",validate:["required"],pointer:{main:p,index:"message"}},{type:"textarea",rows:20,label:"Your config file",readonly:!0,value:H,pointer:{main:p,index:"configfile"}},{type:"buttons",buttons:[{type:"save", ++label:"Send","function":function(a){$(a).text("Sending..");$.ajax({type:"POST",url:"https://mistserver.org/contact?skin=plain",data:p,success:function(a){a=$("<span>").html(a);a.find("script").remove();c.html(a[0].innerHTML)}})}}]}]));break;case "Disconnect":mist.user.password="";delete mist.user.authstring;delete mist.user.loggedin;sessionStorage.removeItem("mistLogin");UI.navto("Login");break;default:c.append($("<p>").text("This tab does not exist."))}c.find(".field").filter(function(){var a=$(this).getval(); ++return a==""||a==null?true:false}).each(function(){var a=[];$(this).is("input, select, textarea")?a.push($(this)):a=$(this).find("input, select, textarea");if(a.length){$(a[0]).focus();return false}})}};"origin"in location||(location.origin=location.protocol+"//");var host;host="file://"==location.origin?"http://localhost:4242/api":location.origin+location.pathname.replace(/\/+$/,"")+"/api"; + var mist={data:{},user:{name:"",password:"",host:host},send:function(a,b,c){var b=b||{},c=c||{},c=$.extend(true,{timeOut:3E4,sendData:b},c),d={authorize:{password:mist.user.authstring?MD5(mist.user.password+mist.user.authstring):"",username:mist.user.name}};$.extend(true,d,b);log("Send",$.extend(true,{},b));var e={url:mist.user.host,type:"POST",data:{command:JSON.stringify(d)},dataType:"jsonp",crossDomain:true,timeout:c.timeout*1E3,async:true,error:function(d,e,l){console.warn("connection failed :(", + l);delete mist.user.loggedin;if(!c.hide){switch(e){case "timeout":e=$("<i>").text("The connection timed out. ");break;case "abort":e=$("<i>").text("The connection was aborted. ");break;default:e=$("<i>").text(e+". ").css("text-transform","capitalize")}$("#message").addClass("red").text("An error occurred while attempting to communicate with MistServer:").append($("<br>")).append($("<span>").text(e)).append($("<a>").text("Send server request again").click(function(){mist.send(a,b,c)}))}UI.navto("Login")}, +-success:function(e){log("Receive",$.extend(true,{},e),"as reply to",c.sendData);delete mist.user.loggedin;switch(e.authorize.status){case "OK":if("streams"in e)if(e.streams)if("incomplete list"in e.streams){delete e.streams["incomplete list"];$.extend(mist.data.streams,e.streams)}else mist.data.streams=e.streams;else mist.data.streams={};var f=$.extend({},e),l=["config","capabilities","ui_settings","LTS","active_streams","browse","log","totals","bandwidth"],o;for(o in f)l.indexOf(o)==-1&&delete f[o]; +-if("bandwidth"in d&&!("bandwidth"in e))f.bandwidth=null;$.extend(mist.data,f);mist.user.loggedin=true;UI.elements.connection.status.text("Connected").removeClass("red").addClass("green");UI.elements.connection.user_and_host.text(mist.user.name+" @ "+mist.user.host);UI.elements.connection.msg.removeClass("red").text("Last communication with the server at "+UI.format.time((new Date).getTime()/1E3));e.LTS&&UI.elements.menu.find(".LTSonly").removeClass("LTSonly");if(e.log){f=e.log[e.log.length-1];UI.elements.connection.msg.append($("<br>")).append($("<span>").text("Last log entry: "+ +-UI.format.time(f[0])+" ["+f[1]+"] "+f[2]))}if("totals"in e){f=function(a,b,c){var d;d=function(){for(var a in c.fields)e[c.fields[a]].push([m,0])};var e={},f;for(f in c.fields)e[c.fields[f]]=[];var l=0,m;if(c.data){if(c.start>mist.data.config.time-600){m=(mist.data.config.time-600)*1E3;d();m=c.start*1E3;d()}else m=c.start*1E3;for(f in c.data){if(f==0){m=c.start*1E3;var o=0}else{m=m+c.interval[o][1]*1E3;c.interval[o][0]--;if(c.interval[o][0]<=0){o++;o<c.interval.length-1&&(l=l+2)}}if(l%2==1){d();l--}for(var t in c.data[f])e[c.fields[t]].push([m, +-c.data[f][t]]);if(l){d();l--}}if(mist.data.config.time-c.end>20){d();m=(mist.data.config.time-15)*1E3;d()}}else{m=(mist.data.config.time-600)*1E3;d();m=(mist.data.config.time-15)*1E3;d()}d=e;stream=a?a.join(" "):"all_streams";protocol=b?b.join("_"):"all_protocols";stream in mist.data.totals||(mist.data.totals[stream]={});protocol in mist.data.totals[stream]||(mist.data.totals[stream][protocol]={});$.extend(mist.data.totals[stream][protocol],d)};mist.data.totals={};if("fields"in e.totals)f(b.totals.streams, +-b.totals.protocols,e.totals);else for(o in e.totals)f(b.totals[o].streams,b.totals[o].protocols,e.totals[o])}a&&a(e,c);break;case "CHALL":if(e.authorize.challenge==mist.user.authstring){mist.user.password!=""&&UI.elements.connection.msg.text("The credentials you provided are incorrect.").addClass("red");UI.navto("Login")}else if(mist.user.password=="")UI.navto("Login");else{mist.user.authstring=e.authorize.challenge;mist.send(a,b,c);sessionStorage.setItem("mistLogin",JSON.stringify({host:mist.user.host, ++success:function(e){log("Receive",$.extend(true,{},e),"as reply to",c.sendData);delete mist.user.loggedin;switch(e.authorize.status){case "OK":if("streams"in e)if(e.streams)if("incomplete list"in e.streams){delete e.streams["incomplete list"];$.extend(mist.data.streams,e.streams)}else mist.data.streams=e.streams;else mist.data.streams={};var h=$.extend({},e),l=["config","capabilities","ui_settings","LTS","active_streams","browse","log","totals","bandwidth"],m;for(m in h)l.indexOf(m)==-1&&delete h[m]; ++if("bandwidth"in d&&!("bandwidth"in e))h.bandwidth=null;$.extend(mist.data,h);mist.user.loggedin=true;UI.elements.connection.status.text("Connected").removeClass("red").addClass("green");UI.elements.connection.user_and_host.text(mist.user.name+" @ "+mist.user.host);UI.elements.connection.msg.removeClass("red").text("Last communication with the server at "+UI.format.time((new Date).getTime()/1E3));if(e.log){h=e.log[e.log.length-1];UI.elements.connection.msg.append($("<br>")).append($("<span>").text("Last log entry: "+ ++UI.format.time(h[0])+" ["+h[1]+"] "+h[2]))}if("totals"in e){h=function(a,b,c){var d;d=function(){for(var a in c.fields)e[c.fields[a]].push([m,0])};var e={},h;for(h in c.fields)e[c.fields[h]]=[];var l=0,m;if(c.data){if(c.start>mist.data.config.time-600){m=(mist.data.config.time-600)*1E3;d();m=c.start*1E3;d()}else m=c.start*1E3;for(h in c.data){if(h==0){m=c.start*1E3;var n=0}else{m=m+c.interval[n][1]*1E3;c.interval[n][0]--;if(c.interval[n][0]<=0){n++;n<c.interval.length-1&&(l=l+2)}}if(l%2==1){d();l--}for(var t in c.data[h])e[c.fields[t]].push([m, ++c.data[h][t]]);if(l){d();l--}}if(mist.data.config.time-c.end>20){d();m=(mist.data.config.time-15)*1E3;d()}}else{m=(mist.data.config.time-600)*1E3;d();m=(mist.data.config.time-15)*1E3;d()}d=e;stream=a?a.join(" "):"all_streams";protocol=b?b.join("_"):"all_protocols";stream in mist.data.totals||(mist.data.totals[stream]={});protocol in mist.data.totals[stream]||(mist.data.totals[stream][protocol]={});$.extend(mist.data.totals[stream][protocol],d)};mist.data.totals={};if("fields"in e.totals)h(b.totals.streams, ++b.totals.protocols,e.totals);else for(m in e.totals)h(b.totals[m].streams,b.totals[m].protocols,e.totals[m])}a&&a(e,c);break;case "CHALL":if(e.authorize.challenge==mist.user.authstring){mist.user.password!=""&&UI.elements.connection.msg.text("The credentials you provided are incorrect.").addClass("red");UI.navto("Login")}else if(mist.user.password=="")UI.navto("Login");else{mist.user.authstring=e.authorize.challenge;mist.send(a,b,c);sessionStorage.setItem("mistLogin",JSON.stringify({host:mist.user.host, + name:mist.user.name,password:mist.user.password}))}break;case "NOACC":UI.navto("Create a new account");break;case "ACC_MADE":delete b.authorize;mist.send(a,b,c);break;default:UI.navto("Login")}}};c.hide||UI.elements.connection.msg.removeClass("red").text("Data sent, waiting for a reply..").append($("<br>")).append($("<a>").text("Cancel request").click(function(){l.abort()}));var l=$.ajax(e)},inputMatch:function(a,b){if(typeof a=="undefined")return false;typeof a=="string"&&(a=[a]);for(var c in a){var d= +-a[c].replace(/[^\w\s]/g,"\\$&"),d=d.replace(/\\\*/g,".*");if(RegExp("^(?:[a-zA-Z]:)?"+d+"(?:\\?[^\\?]*)?$","i").test(b))return true}return false},convertBuildOptions:function(a,b){function c(a,c,d){var f={label:UI.format.capital(d.name?d.name:c),pointer:{main:b,index:c},validate:[]};e[a]=="required"&&(!("default"in d)||d["default"]=="")&&f.validate.push("required");if("default"in d){f.placeholder=d["default"];if(d.type=="select")for(var j in d.select)if(d.select[j][0]==d["default"]){f.placeholder= +-d.select[j][1];break}}if("help"in d)f.help=d.help;if("unit"in d)f.unit=d.unit;if("placeholder"in d)f.placeholder=d.placeholder;if("type"in d)switch(d.type){case "int":f.type="int";if("max"in d)f.max=d.max;if("min"in d)f.min=d.min;break;case "uint":f.type="int";f.min=0;if("max"in d)f.max=d.max;if("min"in d)f.min=Math.max(f.min,d.min);break;case "json":case "debug":case "inputlist":f.type=d.type;break;case "radioselect":f.type="radioselect";f.radioselect=d.radioselect;break;case "select":f.type="select"; ++a[c].replace(/[^\w\s]/g,"\\$&"),d=d.replace(/\\\*/g,".*");if(RegExp("^(?:[a-zA-Z]:)?"+d+"(?:\\?[^\\?]*)?$","i").test(b))return true}return false},convertBuildOptions:function(a,b){function c(a,c,d){var f={label:UI.format.capital(d.name?d.name:c),pointer:{main:b,index:c},validate:[]};e[a]=="required"&&(!("default"in d)||d["default"]=="")&&f.validate.push("required");if("default"in d){f.placeholder=d["default"];if(d.type=="select")for(var h in d.select)if(d.select[h][0]==d["default"]){f.placeholder= ++d.select[h][1];break}}if("help"in d)f.help=d.help;if("unit"in d)f.unit=d.unit;if("placeholder"in d)f.placeholder=d.placeholder;if("type"in d)switch(d.type){case "int":f.type="int";if("max"in d)f.max=d.max;if("min"in d)f.min=d.min;break;case "uint":f.type="int";f.min=0;if("max"in d)f.max=d.max;if("min"in d)f.min=Math.max(f.min,d.min);break;case "json":case "debug":case "inputlist":f.type=d.type;break;case "radioselect":f.type="radioselect";f.radioselect=d.radioselect;break;case "select":f.type="select"; + f.select=d.select.slice(0);f.validate.indexOf("required")>=0&&f.select.unshift(["","placeholder"in f?"Default ("+f.placeholder+")":""]);break;case "sublist":f.type="sublist";f.saveas={};f.itemLabel=d.itemLabel;f.sublist=mist.convertBuildOptions(d,f.saveas);break;default:f.type="str"}else f.type="checkbox";"influences"in d&&(f["function"]=function(){var a=$(this).closest(".UIelement"),b=a.find("style");if(b.length)b=b[0];else{b=$("<style>").addClass("dependencies")[0];a.append(b)}b.innerHTML=".UIelement[data-dependent-"+ + c+"]:not([data-dependent-"+c+'~="'+$(this).getval()+'"]) { display: none; }\n';$(b).data("content",b.innerHTML);$("style.dependencies.hidden").each(function(){$(this).html($(this).data("content")).removeClass("hidden")});$(".UIelement:not(:visible) style.dependencies:not(.hidden)").each(function(){$(this).addClass("hidden");$(this).html("")})});if("dependent"in d)f.dependent=d.dependent;if("value"in d)f.value=d.value;if("validate"in d)f.validate=f.validate.concat(d.validate);return f}var d=[],e=["required", +-"optional"];"desc"in a&&d.push({type:"help",help:a.desc});for(var l in e)if(a[e[l]]){d.push($("<h4>").text(UI.format.capital(e[l])+" parameters"));var m=Object.keys(a[e[l]]);"sort"in a&&m.sort(function(b,c){return(""+a[e[l]][b][a.sort]).localeCompare(a[e[l]][c][a.sort])});for(var f in m){var t=m[f],o=a[e[l]][t];if(Array.isArray(o))for(var k in o)d.push(c(l,t,o[k]));else d.push(c(l,t,o))}}return d},stored:{get:function(){return mist.data.ui_settings||{}},set:function(a,b){var c=this.get();c[a]=b;mist.send(function(){}, ++"optional"];"desc"in a&&d.push({type:"help",help:a.desc});for(var l in e)if(a[e[l]]){d.push($("<h4>").text(UI.format.capital(e[l])+" parameters"));var n=Object.keys(a[e[l]]);"sort"in a&&n.sort(function(b,c){return(""+a[e[l]][b][a.sort]).localeCompare(a[e[l]][c][a.sort])});for(var h in n){var t=n[h],m=a[e[l]][t];if(Array.isArray(m))for(var k in m)d.push(c(l,t,m[k]));else d.push(c(l,t,m))}}return d},stored:{get:function(){return mist.data.ui_settings||{}},set:function(a,b){var c=this.get();c[a]=b;mist.send(function(){}, + {ui_settings:c})},del:function(a){delete mist.data.ui_settings[a];mist.send(function(){},{ui_settings:mist.data.ui_settings})}}};function log(){try{UI.debug&&[].push.call(arguments,Error().stack);[].unshift.call(arguments,"["+UI.format.time((new Date).getTime()/1E3)+"]");console.log.apply(console,arguments)}catch(a){}} + $.fn.getval=function(){var a=$(this).data("opts"),b=$(this).val();if(a&&"type"in a)switch(a.type){case "int":b!=""&&(b=Number(b));break;case "span":b=$(this).html();break;case "debug":b=$(this).val()==""?null:Number($(this).val());break;case "checkbox":b=$(this).prop("checked");break;case "radioselect":a=$(this).find("label > input[type=radio]:checked").parent();if(a.length){b=[];b.push(a.children("input[type=radio]").val());a=a.children("select");a.length&&b.push(a.val())}else b="";break;case "checklist":b= + [];$(this).find(".checklist input[type=checkbox]:checked").each(function(){b.push($(this).attr("name"))});break;case "unix":b!=""&&(b=Math.round(new Date($(this).val())/1E3));break;case "selectinput":b=$(this).children("select").first().val();b=="CUSTOM"&&(b=$(this).children("label").first().find(".field_container").children().first().getval());break;case "inputlist":b=[];$(this).children().each(function(){$(this).val()!=""&&b.push($(this).val())});break;case "sublist":b=$(this).data("savelist"); +-break;case "json":try{b=JSON.parse($(this).val())}catch(c){b=null}}return b}; ++break;case "json":try{b=JSON.parse($(this).val())}catch(c){b=null}break;case "bitmask":b=0;$(this).find("input").each(function(){$(this).prop("checked")&&(b=b+Number($(this).val()))})}return b}; + $.fn.setval=function(a){var b=$(this).data("opts");$(this).val(a);if(b&&"type"in b)switch(b.type){case "span":$(this).html(a);break;case "checkbox":$(this).prop("checked",a);break;case "geolimited":case "hostlimited":b=$(this).closest(".field_container").data("subUI");if(typeof a=="undefined"||a.length==0)a="-";b.blackwhite.val(a.charAt(0));var a=a.substr(1).split(" "),c;for(c in a)b.values.append(b.prototype.clone(true).val(a[c]));b.blackwhite.trigger("change");break;case "radioselect":if(typeof a== + "undefined")return $(this);c=$(this).find('label > input[type=radio][value="'+a[0]+'"]').prop("checked",true).parent();a.length>1&&c.children("select").val(a[1]);break;case "checklist":b=$(this).find(".checklist input[type=checkbox]").prop("checked",false);for(c in a)b.filter('[name="'+a[c]+'"]').prop("checked",true);break;case "unix":if(typeof a!="undefined"){a=new Date(Math.round(a)*1E3);a.setMinutes(a.getMinutes()-a.getTimezoneOffset());a=a.toISOString();$(this).val(a.split("Z")[0])}break;case "selectinput":a=== + null&&(a="");var d=false;for(c in b.selectinput){var e;typeof b.selectinput[c]=="string"?e=b.selectinput[c]:typeof b.selectinput[c][0]=="string"&&(e=b.selectinput[c][0]);if(e==a){$(this).children("select").first().val(a);d=true;break}}if(!d){$(this).children("label").first().find(".field_container").children().first().setval(a);$(this).children("select").first().val("CUSTOM").trigger("change")}break;case "inputlist":typeof a=="string"&&(a=[a]);for(c in a)$(this).append($(this).data("newitem")().val(a[c])); +-$(this).append($(this).children().first());break;case "sublist":var l=$(this),b=$(this).children(".curvals");b.html("");if(a&&a.length)for(c in a){var d=$.extend(true,{},a[c]),m=function(a){for(var b in a)b.slice(0,6)=="x-LSP-"?delete a[b]:typeof a[b]=="object"&&m(a[b])};m(d);b.append($("<div>").addClass("subitem").append($("<span>").addClass("itemdetails").text(a[c]["x-LSP-name"]?a[c]["x-LSP-name"]:JSON.stringify(d)).attr("title",JSON.stringify(d,null,2))).append($("<button>").addClass("move").text("^").attr("title", ++$(this).append($(this).children().first());break;case "sublist":var l=$(this),b=$(this).children(".curvals");b.html("");if(a&&a.length)for(c in a){var d=$.extend(true,{},a[c]),n=function(a){for(var b in a)b.slice(0,6)=="x-LSP-"?delete a[b]:typeof a[b]=="object"&&n(a[b])};n(d);b.append($("<div>").addClass("subitem").append($("<span>").addClass("itemdetails").text(a[c]["x-LSP-name"]?a[c]["x-LSP-name"]:JSON.stringify(d)).attr("title",JSON.stringify(d,null,2))).append($("<button>").addClass("move").text("^").attr("title", + "Move item up").click(function(){var a=$(this).parent().index();if(a!=0){var b=l.getval();b.splice(a-1,0,b.splice(a,1)[0]);l.setval(b)}})).append($("<button>").text("Edit").click(function(){var a=$(this).parent().index(),b=$(this).closest(".field");b.data("build")(Object.assign({},b.getval()[a]),a)})).append($("<button>").text("x").attr("title","Remove item").click(function(a){var b=$(this).parent().index(),c=l.data("savelist");c.splice(b,1);l.setval(c);a.preventDefault()})))}else b.append("None."); +-l.data("savelist",a);break;case "json":$(this).val(a===null?"":JSON.stringify(a,null,2))}$(this).trigger("change");return $(this)};function parseURL(a,b){var c=document.createElement("a");c.href=a;if(b)for(var d in b)c[d]=b[d];return{full:c.href,protocol:c.protocol+"//",host:c.hostname,port:c.port?":"+c.port:""}}function triggerRewrite(a){return typeof a=="object"&&typeof a.length=="undefined"?a:obj={handler:a[0],sync:a[1],streams:a[2],"default":a[3]}}; ++l.data("savelist",a);break;case "json":$(this).val(a===null?"":JSON.stringify(a,null,2));break;case "bitmask":d=$(this).data("opts").bitmask;b=$(this).find("input");for(c in d){$el=b.eq(c);(a&d[c][0])==d[c][0]?$el.attr("checked","checked"):$el.removeAttr("checked")}}$(this).trigger("change");return $(this)};function parseURL(a,b){var c=document.createElement("a");c.href=a;if(b)for(var d in b)c[d]=b[d];return{full:c.href,protocol:c.protocol+"//",host:c.hostname,port:c.port?":"+c.port:""}} ++function triggerRewrite(a){return typeof a=="object"&&typeof a.length=="undefined"?a:obj={handler:a[0],sync:a[1],streams:a[2],"default":a[3]}}; +diff --git a/lsp/mist.js b/lsp/mist.js +index 4187b75b..c85d2eb0 100644 +--- a/lsp/mist.js ++++ b/lsp/mist.js +@@ -249,6 +249,7 @@ var UI = { + menu: [ + { + Overview: {}, ++ General: {}, + Protocols: {}, + Streams: { + hiddenmenu: { +@@ -257,12 +258,8 @@ var UI = { + Embed: {} + } + }, +- Push: { +- LTSonly: true +- }, +- 'Triggers': { +- LTSonly: false +- }, ++ Push: {}, ++ Triggers: {}, + Logs: {}, + Statistics: {}, + 'Server Stats': {} +@@ -300,9 +297,6 @@ var UI = { + for (var k in button.classes) { + $button.addClass(button.classes[k]); + } +- if ('LTSonly' in button) { +- $button.addClass('LTSonly'); +- } + if ('link' in button) { + $button.attr('href',button.link).attr('target','_blank'); + } +@@ -598,7 +592,7 @@ var UI = { + $field = $('<div>').addClass('radioselect'); + for (var i in e.radioselect) { + var $radio = $('<input>').attr('type','radio').val(e.radioselect[i][0]).attr('name',e.label); +- if ((('LTSonly' in e) && (!mist.data.LTS)) || (e.readonly)) { ++ if (e.readonly) { + $radio.prop('disabled',true); + } + var $label = $('<label>').append( +@@ -612,7 +606,7 @@ var UI = { + $(this).parent().find('input[type=radio]:enabled').prop('checked','true'); + }); + $label.append($select); +- if ((('LTSonly' in e) && (!mist.data.LTS)) || (e.readonly)) { ++ if (e.readonly) { + $select.prop('disabled',true); + } + for (var j in e.radioselect[i][2]) { +@@ -659,10 +653,6 @@ var UI = { + $field.append($select); + $select.data("input",false); + +- if (('LTSonly' in e) && (!mist.data.LTS)) { +- $select.prop('disabled',true); +- } +- + for (var i in e.selectinput) { + var $option = $("<option>"); + $select.append($option); +@@ -699,7 +689,7 @@ var UI = { + $field = $('<div>').addClass('inputlist'); + var newitem = function(){ + var $part = $("<input>").attr("type","text").addClass("listitem"); +- if ((('LTSonly' in e) && (!mist.data.LTS)) || (e.readonly)) { ++ if (e.readonly) { + $part.prop('disabled',true); + } + var keyup = function(e){ +@@ -832,7 +822,7 @@ var UI = { + $c.append($itemsettings); + break; + } +- case "json": ++ case "json": { + $field = $("<textarea>").on('keydown',function(e){ + e.stopPropagation(); + }).on('keyup change',function(e){ +@@ -855,6 +845,23 @@ var UI = { + e.validate = [f]; + } + break; ++ } ++ case "bitmask": { ++ $field = $("<div>").addClass("bitmask"); ++ for (var i in e.bitmask) { ++ $field.append( ++ $("<label>").append( ++ $("<input>").attr("type","checkbox").attr("name","bitmask_"+("pointer" in e ? e.pointer.index : "")).attr("value",e.bitmask[i][0]).addClass("field") ++ ).append( ++ $("<span>").text(e.bitmask[i][1]) ++ ) ++ ); ++ } ++ ++ //when the main label is clicked, do nothing (instead of toggeling the first checkbox) ++ $e.attr("for","none"); ++ break; ++ } + default: + $field = $('<input>').attr('type','text'); + } +@@ -941,10 +948,6 @@ var UI = { + if ('rows' in e) { + $field.attr('rows',e.rows); + } +- if (('LTSonly' in e) && (!mist.data.LTS)) { +- $fc.addClass('LTSonly'); +- $field.prop('disabled',true); +- } + if ("dependent" in e) { + for (var i in e.dependent) { + $e.attr("data-dependent-"+i,e.dependent[i]); +@@ -1128,10 +1131,6 @@ var UI = { + } + subUI.field.trigger('change'); + }); +- if (('LTSonly' in e) && (!mist.data.LTS)) { +- subUI.blackwhite.prop('disabled',true); +- subUI.prototype.prop('disabled',true); +- } + subUI.values.append(subUI.prototype.clone(true)); + $fc.data('subUI',subUI).addClass('limit_list').append(subUI.blackwhite).append(subUI.values); + break; +@@ -2393,34 +2392,10 @@ var UI = { + var $protocols_on = $('<span>'); + var $protocols_off = $('<span>'); + +- var s = { +- serverid: mist.data.config.serverid, +- debug: mist.data.config.debug, +- accesslog: mist.data.config.accesslog, +- prometheus: mist.data.config.prometheus, +- defaultStream: mist.data.config.defaultStream, +- trustedproxy: mist.data.config.trustedproxy, +- location: "location" in mist.data.config ? mist.data.config.location : {} +- }; +- var b = {}; +- if ("bandwidth" in mist.data) { +- b = mist.data.bandwidth; +- if (b == null) { b = {}; } +- if (!b.limit) { +- b.limit = ""; +- } +- } +- var $bitunit = $("<select>").html( +- $("<option>").val(1).text("bytes/s") +- ).append( +- $("<option>").val(1024).text("KiB/s") +- ).append( +- $("<option>").val(1048576).text("MiB/s") +- ).append( +- $("<option>").val(1073741824).text("GiB/s") +- ); + var host = parseURL(mist.user.host); + host = host.protocol+host.host+host.port; ++ ++ var s = {}; + + $main.append(UI.buildUI([ + { +@@ -2436,8 +2411,7 @@ var UI = { + },{ + type: 'span', + label: 'Version check', +- value: $versioncheck, +- LTSonly: true ++ value: $versioncheck + },{ + type: 'span', + label: 'Server time', +@@ -2445,13 +2419,11 @@ var UI = { + },{ + type: 'span', + label: 'Licensed to', +- value: ("license" in mist.data.config ? mist.data.config.license.user : ""), +- LTSonly: true ++ value: ("license" in mist.data.config ? mist.data.config.license.user : "") + },{ + type: 'span', + label: 'Active licenses', +- value: $activeproducts, +- LTSonly: true ++ value: $activeproducts + },{ + type: 'span', + label: 'Configured streams', +@@ -2476,156 +2448,26 @@ var UI = { + type: 'span', + label: 'Recent problems', + value: $errors +- },$('<br>'),{ +- type: 'str', +- label: 'Human readable name', +- pointer: { +- main: s, +- index: 'serverid' +- }, +- help: 'You can name your MistServer here for personal use. You\'ll still need to set host name within your network yourself.' +- },{ +- type: 'debug', +- label: 'Debug level', +- pointer: { +- main: s, +- index: 'debug' +- }, +- help: 'You can set the amount of debug information MistServer saves in the log. A full reboot of MistServer is required before some components of MistServer can post debug information.' +- },{ +- type: "selectinput", +- label: "Access log", +- selectinput: [ +- ["","Do not track"], +- ["LOG","Log to MistServer log"], +- [{ +- type:"str", +- label:"Path", +- LTSonly: true +- },"Log to file"] +- ], +- pointer: { +- main: s, +- index: "accesslog" +- }, +- help: "Enable access logs.", +- LTSonly: true +- },{ +- type: "selectinput", +- label: "Prometheus stats output", +- selectinput: [ +- ["","Disabled"], +- [{ +- type: "str", +- label:"Passphrase", +- LTSonly: true +- },"Enabled"] +- ], +- pointer: { +- main: s, +- index: "prometheus" +- }, +- help: "Make stats available in Prometheus format. These can be accessed via "+host+"/PASSPHRASE or "+host+"/PASSPHRASE.json.", +- LTSonly: true +- },{ +- type: "inputlist", +- label: "Trusted proxies", +- help: "List of proxy server addresses that are allowed to override the viewer IP address to arbitrary values.<br>You may use a hostname or IP address.", +- LTSonly: true, +- pointer: { +- main: s, +- index: "trustedproxy" +- } +- },{ +- type: "selectinput", +- label: "Load balancer bandwidth limit", +- selectinput: [ +- ["","Default (1 gbps)"], +- [{ +- label: "Custom", +- type: "int", +- min: 0, +- unit: $bitunit +- },"Custom"] +- ], +- pointer: { +- main: b, +- index: "limit" +- }, +- help: "This setting only applies when MistServer is combined with a load balancer. This is the amount of traffic this server is willing to handle.", +- LTSonly: true +- },{ +- type: "inputlist", +- label: "Load balancer bandwidth exceptions", +- pointer: { +- main: b, +- index: "exceptions" +- }, +- help: "This setting only applies when MistServer is combined with a load balancer. Data sent to the hosts and subnets listed here will not count towards reported bandwidth usage.<br>Examples:<ul><li>192.168.0.0/16</li><li>localhost</li><li>10.0.0.0/8</li><li>fe80::/16</li></ul>", +- LTSonly: true +- },{ +- type: "int", +- step: 0.00000001, +- label: "Server latitude", +- pointer: { +- main: s.location, +- index: "lat" +- }, +- help: "This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them.", +- LTSonly: true +- },{ +- type: "int", +- step: 0.00000001, +- label: "Server longitude", +- pointer: { +- main: s.location, +- index: "lon" +- }, +- help: "This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them.", +- LTSonly: true +- },{ +- type: "str", +- label: "Server location name", +- pointer: { +- main: s.location, +- index: "name" +- }, +- help: "This setting is only useful when MistServer is combined with a load balancer. This will be displayed as the server's location.", +- LTSonly: true +- },{ +- type: "str", +- validate: ['streamname_with_wildcard_and_variables'], +- label: 'Fallback stream', +- pointer: { +- main: s, +- index: "defaultStream" +- }, +- help: "When this is set, if someone attempts to view a stream that does not exist, or is offline, they will be redirected to this stream instead. $stream may be used to refer to the original stream name.", +- LTSonly: true ++ }, ++ $("<br>"), ++ $("<h3>").text("Write config now"), ++ { ++ type: "help", ++ help: "Tick the box in order to force an immediate save to the config.json MistServer uses to save your settings. Saving will otherwise happen upon closing MistServer. Don\'t forget to press save after ticking the box." + },{ + type: 'checkbox', + label: 'Force configurations save', + pointer: { + main: s, + index: 'save' +- }, +- help: 'Tick the box in order to force an immediate save to the config.json MistServer uses to save your settings. Saving will otherwise happen upon closing MistServer. Don\'t forget to press save after ticking the box.' ++ } + },{ + type: 'buttons', + buttons: [{ + type: 'save', + label: 'Save', + 'function': function(){ +- var save = {config: s}; +- +- var bandwidth = {}; +- bandwidth.limit = (b.limit ? $bitunit.val() * b.limit : 0); +- bandwidth.exceptions = b.exceptions; +- if (bandwidth.exceptions === null) { +- bandwidth.exceptions = []; +- } +- +- save.bandwidth = bandwidth; ++ var save = {}; + + if (s.save) { + save.save = s.save; +@@ -2857,6 +2699,289 @@ var UI = { + UI.interval.set(updateViewers,30e3); + + break; ++ case 'General': { ++ ++ var s = { ++ serverid: mist.data.config.serverid, ++ debug: mist.data.config.debug, ++ accesslog: mist.data.config.accesslog, ++ prometheus: mist.data.config.prometheus, ++ sessionViewerMode: mist.data.config.sessionViewerMode, ++ sessionInputMode: mist.data.config.sessionInputMode, ++ sessionOutputMode: mist.data.config.sessionOutputMode, ++ sessionUnspecifiedMode: mist.data.config.sessionUnspecifiedMode, ++ tknMode: mist.data.config.tknMode, ++ sessionStreamInfoMode: mist.data.config.sessionStreamInfoMode, ++ defaultStream: mist.data.config.defaultStream, ++ trustedproxy: mist.data.config.trustedproxy, ++ location: "location" in mist.data.config ? mist.data.config.location : {} ++ }; ++ var b = {}; ++ if ("bandwidth" in mist.data) { ++ b = mist.data.bandwidth; ++ if (b == null) { b = {}; } ++ if (!b.limit) { ++ b.limit = ""; ++ } ++ } ++ var $bitunit = $("<select>").html( ++ $("<option>").val(1).text("bytes/s") ++ ).append( ++ $("<option>").val(1024).text("KiB/s") ++ ).append( ++ $("<option>").val(1048576).text("MiB/s") ++ ).append( ++ $("<option>").val(1073741824).text("GiB/s") ++ ); ++ ++ ++ $main.html(UI.buildUI([ ++ $("<h2>").text("General settings"),{ ++ type: "help", ++ help: "These are settings that apply to your MistServer instance in general." ++ },{ ++ type: 'str', ++ label: 'Human readable name', ++ pointer: { ++ main: s, ++ index: 'serverid' ++ }, ++ help: 'You can name your MistServer here for personal use. You\'ll still need to set host name within your network yourself.' ++ },{ ++ type: 'debug', ++ label: 'Debug level', ++ pointer: { ++ main: s, ++ index: 'debug' ++ }, ++ help: 'You can set the amount of debug information MistServer saves in the log. A full reboot of MistServer is required before some components of MistServer can post debug information.' ++ },{ ++ type: "selectinput", ++ label: "Access log", ++ selectinput: [ ++ ["","Do not track"], ++ ["LOG","Log to MistServer log"], ++ [{ ++ type:"str", ++ label:"Path" ++ },"Log to file"] ++ ], ++ pointer: { ++ main: s, ++ index: "accesslog" ++ }, ++ help: "Enable access logs." ++ },{ ++ type: "selectinput", ++ label: "Prometheus stats output", ++ selectinput: [ ++ ["","Disabled"], ++ [{ ++ type: "str", ++ label:"Passphrase" ++ },"Enabled"] ++ ], ++ pointer: { ++ main: s, ++ index: "prometheus" ++ }, ++ help: "Make stats available in Prometheus format. These can be accessed via "+host+"/PASSPHRASE or "+host+"/PASSPHRASE.json." ++ },{ ++ type: "inputlist", ++ label: "Trusted proxies", ++ help: "List of proxy server addresses that are allowed to override the viewer IP address to arbitrary values.<br>You may use a hostname or IP address.", ++ pointer: { ++ main: s, ++ index: "trustedproxy" ++ } ++ },{ ++ type: "str", ++ validate: ['streamname_with_wildcard_and_variables'], ++ label: 'Fallback stream', ++ pointer: { ++ main: s, ++ index: "defaultStream" ++ }, ++ help: "When this is set, if someone attempts to view a stream that does not exist, or is offline, they will be redirected to this stream instead. $stream may be used to refer to the original stream name." ++ }, ++ ++ ++ ++ $("<h3>").text("Sessions"), ++ ++ { ++ type: 'bitmask', ++ label: 'Bundle viewer sessions by', ++ bitmask: [ ++ [8,"Stream name"], ++ [4,"IP address"], ++ [2,"Token"], ++ [1,"Protocol"] ++ ], ++ pointer: { ++ main: s, ++ index: 'sessionViewerMode' ++ }, ++ help: 'Change the way viewer connections are bundled into sessions.<br>Default: stream name, viewer IP and token' ++ },{ ++ type: 'bitmask', ++ label: 'Bundle input sessions by', ++ bitmask: [ ++ [8,"Stream name"], ++ [4,"IP address"], ++ [2,"Token"], ++ [1,"Protocol"] ++ ], ++ pointer: { ++ main: s, ++ index: 'sessionInputMode' ++ }, ++ help: 'Change the way input connections are bundled into sessions.<br>Default: stream name, input IP, token and protocol' ++ },{ ++ type: 'bitmask', ++ label: 'Bundle output sessions by', ++ bitmask: [ ++ [8,"Stream name"], ++ [4,"IP address"], ++ [2,"Token"], ++ [1,"Protocol"] ++ ], ++ pointer: { ++ main: s, ++ index: 'sessionOutputMode' ++ }, ++ help: 'Change the way output connections are bundled into sessions.<br>Default: stream name, output IP, token and protocol' ++ },{ ++ type: 'bitmask', ++ label: 'Bundle unspecified sessions by', ++ bitmask: [ ++ [8,"Stream name"], ++ [4,"IP address"], ++ [2,"Token"], ++ [1,"Protocol"] ++ ], ++ pointer: { ++ main: s, ++ index: 'sessionUnspecifiedMode' ++ }, ++ help: 'Change the way unspecified connections are bundled into sessions.<br>Default: none' ++ },{ ++ type: 'select', ++ label: 'Treat HTTP-only sessions as', ++ select: [ ++ [1, 'A viewer session'], ++ [2, 'An output session: skip executing the USER_NEW and USER_END triggers'], ++ [4, 'A separate \'unspecified\' session: skip executing the USER_NEW and USER_END triggers'], ++ [3, 'Do not start a session: skip executing the USER_NEW and USER_END triggers and do not count for statistics'] ++ ], ++ pointer: { ++ main: s, ++ index: 'sessionStreamInfoMode' ++ }, ++ help: 'Change the way the stream info connection gets treated.<br>Default: as a viewer session' ++ },{ ++ type: "bitmask", ++ label: "Communicate session token", ++ bitmask: [ ++ [8,"Write to cookie"], ++ [4,"Write to URL parameter"], ++ [2,"Read from cookie"], ++ [1,"Read from URL parameter"] ++ ], ++ pointer: { ++ main: s, ++ index: "tknMode" ++ }, ++ help: "Change the way the session token gets passed to and from MistServer, which can be set as a cookie or URL parameter named `tkn`. Reading the session token as a URL parameter takes precedence over reading from the cookie.<br>Default: all" ++ }, ++ ++ ++ ++ $('<h3>').text("Load balancer"), ++ { ++ type: "help", ++ help: "If you're using MistServer's load balancer, the information below is passed to it so that it can make informed decisions." ++ }, ++ ++ { ++ type: "selectinput", ++ label: "Server's bandwidth limit", ++ selectinput: [ ++ ["","Default (1 gbps)"], ++ [{ ++ label: "Custom", ++ type: "int", ++ min: 0, ++ unit: $bitunit ++ },"Custom"] ++ ], ++ pointer: { ++ main: b, ++ index: "limit" ++ }, ++ help: "This is the amount of traffic this server is willing to handle." ++ },{ ++ type: "inputlist", ++ label: "Bandwidth exceptions", ++ pointer: { ++ main: b, ++ index: "exceptions" ++ }, ++ help: "Data sent to the hosts and subnets listed here will not count towards reported bandwidth usage.<br>Examples:<ul><li>192.168.0.0/16</li><li>localhost</li><li>10.0.0.0/8</li><li>fe80::/16</li></ul>" ++ },{ ++ type: "int", ++ step: 0.00000001, ++ label: "Server latitude", ++ pointer: { ++ main: s.location, ++ index: "lat" ++ }, ++ help: "This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them." ++ },{ ++ type: "int", ++ step: 0.00000001, ++ label: "Server longitude", ++ pointer: { ++ main: s.location, ++ index: "lon" ++ }, ++ help: "This setting is only useful when MistServer is combined with a load balancer. When this is set, the balancer can send users to a server close to them." ++ },{ ++ type: "str", ++ label: "Server location name", ++ pointer: { ++ main: s.location, ++ index: "name" ++ }, ++ help: "This setting is only useful when MistServer is combined with a load balancer. This will be displayed as the server's location." ++ },{ ++ type: 'buttons', ++ buttons: [{ ++ type: 'save', ++ label: 'Save', ++ 'function': function(ele){ ++ $(ele).text("Saving.."); ++ ++ var save = {config: s}; ++ ++ var bandwidth = {}; ++ bandwidth.limit = (b.limit ? $bitunit.val() * b.limit : 0); ++ bandwidth.exceptions = b.exceptions; ++ if (bandwidth.exceptions === null) { ++ bandwidth.exceptions = []; ++ } ++ save.bandwidth = bandwidth; ++ ++ mist.send(function(){ ++ UI.navto('Overview'); ++ },save) ++ } ++ }] ++ } ++ ++ ])); ++ break; ++ } + case 'Protocols': + if (typeof mist.data.capabilities == 'undefined') { + mist.send(function(d){ +@@ -3832,7 +3957,7 @@ var UI = { + Linux/MacOS: /PATH/<br>\ + Windows: /cygdrive/DRIVE/PATH/\ + </td>\ +- <td class=LTSonly>\ ++ <td>\ + A folder stream makes all the recognised files in the selected folder available as a stream.\ + </td>\ + </tr>\ +@@ -3851,12 +3976,12 @@ var UI = { + <tr>\ + <th>RTSP</th>\ + <td>push://(IP)(@PASSWORD)</td>\ +- <td class=LTSonly>IP is white listed IP for pushing towards MistServer, if left empty all are white listed.</td>\ ++ <td>IP is white listed IP for pushing towards MistServer, if left empty all are white listed.</td>\ + </tr>\ + <tr>\ + <th>TS</th>\ + <td>tsudp://(IP):PORT(/INTERFACE)</td>\ +- <td class=LTSonly>\ ++ <td>\ + IP is the IP address used to listen for this stream, multi-cast IP range is: 224.0.0.0 - 239.255.255.255. If IP is not set all addresses will listened to.<br>\ + PORT is the port you reserve for this stream on the chosen IP.<br>\ + INTERFACE is the interface used, if left all interfaces will be used.\ +@@ -3877,19 +4002,19 @@ var UI = { + <tr>\ + <th>HLS</th>\ + <td>http://URL/TO/STREAM.m3u8</td>\ +- <td class=LTSonly>The URL where the HLS stream is available to MistServer.</td>\ ++ <td>The URL where the HLS stream is available to MistServer.</td>\ + </tr>\ + <tr>\ + <th>RTSP</th>\ + <td>rtsp://(USER:PASSWORD@)IP(:PORT)(/path)</td>\ +- <td class=LTSonly>\ ++ <td>\ + USER:PASSWORD is the account used if authorization is required.<br>\ + IP is the IP address used to pull this stream from.<br>\ + PORT is the port used to connect through.<br>\ + PATH is the path to be used to identify the correct stream.\ + </td>\ + </tr>\ +- </table>").replace(/LTSonly/g,(mist.data.LTS ? "\"\"" : "LTSonly")) ++ </table>") + , + 'function': function(){ + var source = $(this).val(); +@@ -3993,7 +4118,6 @@ var UI = { + label: 'Stop sessions', + type: 'checkbox', + help: 'When saving these stream settings, kill this stream\'s current connections.', +- LTSonly: true, + pointer: { + main: saveas, + index: 'stop_sessions' +@@ -5287,8 +5411,7 @@ var UI = { + pointer: { + main: push_settings, + index: 'wait' +- }, +- LTSonly: 1 ++ } + },{ + label: 'Maximum retries', + unit: '/s', +@@ -5299,8 +5422,7 @@ var UI = { + pointer: { + main: push_settings, + index: 'maxspeed' +- }, +- LTSonly: 1 ++ } + },{ + type: 'buttons', + buttons: [{ +@@ -5556,8 +5678,7 @@ var UI = { + "break": false + }; + }], +- datalist: allthestreams, +- LTSonly: 1 ++ datalist: allthestreams + },{ + label: 'Target', + type: 'str', +@@ -5622,8 +5743,7 @@ var UI = { + optional: mist.data.capabilities.connectors[match].push_parameters + }; + $additional_params.append(UI.buildUI(mist.convertBuildOptions(capa,saveas.params))); +- }, +- LTSonly: 1 ++ } + },$additional_params]; + + +@@ -5909,7 +6029,6 @@ var UI = { + help: 'For what event this trigger should activate.', + type: 'select', + select: triggerSelect, +- LTSonly: true, + validate: ['required'], + 'function': function(){ + var v = $(this).getval(); +@@ -5992,8 +6111,7 @@ var UI = { + }, + help: 'For triggers that can apply to specific streams, this value decides what streams they are triggered for. (none checked = always triggered)', + type: 'checklist', +- checklist: Object.keys(mist.data.streams), +- LTSonly: true ++ checklist: Object.keys(mist.data.streams) + },$('<br>'),{ + label: 'Handler (URL or executable)', + help: 'This can be either an HTTP URL or a full path to an executable.', +@@ -6002,8 +6120,7 @@ var UI = { + index: 'url' + }, + validate: ['required'], +- type: 'str', +- LTSonly: true ++ type: 'str' + },{ + label: 'Blocking', + type: 'checkbox', +@@ -6011,8 +6128,7 @@ var UI = { + pointer: { + main: saveas, + index: 'async' +- }, +- LTSonly: true ++ } + },{ + label: 'Parameters', + type: 'str', +@@ -6020,8 +6136,7 @@ var UI = { + pointer: { + main: saveas, + index: 'params' +- }, +- LTSonly: true ++ } + },{ + label: 'Default response', + type: 'str', +@@ -6030,8 +6145,7 @@ var UI = { + pointer: { + main: saveas, + index: 'default' +- }, +- LTSonly: true ++ } + },{ + type: 'buttons', + buttons: [ +@@ -6730,8 +6844,6 @@ var mist = { + UI.elements.connection.user_and_host.text(mist.user.name+' @ '+mist.user.host); + UI.elements.connection.msg.removeClass('red').text('Last communication with the server at '+UI.format.time((new Date).getTime()/1000)); + +- //if this is LTS, get rid of the banner on menu buttons +- if (d.LTS) { UI.elements.menu.find('.LTSonly').removeClass('LTSonly'); } + + if (d.log) { + var lastlog = d.log[d.log.length-1]; +@@ -7181,6 +7293,15 @@ $.fn.getval = function(){ + val = null; + } + break; ++ case "bitmask": { ++ val = 0; ++ $(this).find("input").each(function(){ ++ if ($(this).prop("checked")) { ++ val += Number($(this).val()); ++ } ++ }); ++ break; ++ } + } + } + return val; +@@ -7327,6 +7448,21 @@ $.fn.setval = function(val){ + break; + case "json": { + $(this).val(val === null ? "" : JSON.stringify(val,null,2)); ++ break; ++ } ++ case "bitmask": { ++ var map = $(this).data("opts").bitmask; ++ var $inputs = $(this).find("input"); ++ for (var i in map) { ++ $el = $inputs.eq(i); ++ if ((val & map[i][0]) == map[i][0]) { ++ $el.attr("checked","checked"); ++ } ++ else { ++ $el.removeAttr("checked"); ++ } ++ } ++ break; + } + } + } +-- +2.25.1 + + +From 7098f8430b3a9901e2c819c7bc562e3f99f6e19a Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 6 Oct 2022 16:23:29 +0200 +Subject: [PATCH 29/38] Update input codec capabilities to be more + consistent/accurate, and more easily automatically parsed + +--- + src/input/input_aac.cpp | 2 +- + src/input/input_av.cpp | 10 ++++----- + src/input/input_balancer.cpp | 3 --- + src/input/input_buffer.cpp | 3 --- + src/input/input_dtsc.cpp | 14 ++++++------- + src/input/input_ebml.cpp | 40 ++++++++++++++++++------------------ + src/input/input_flv.cpp | 10 ++++----- + src/input/input_h264.cpp | 2 +- + src/input/input_hls.cpp | 8 ++++---- + src/input/input_ismv.cpp | 4 ++-- + src/input/input_mp3.cpp | 2 +- + src/input/input_mp4.cpp | 14 ++++++------- + src/input/input_ogg.cpp | 6 +++--- + src/input/input_rtsp.cpp | 26 +++++++++++------------ + src/input/input_sdp.cpp | 26 +++++++++++------------ + src/input/input_srt.cpp | 2 +- + src/input/input_ts.cpp | 16 +++++++-------- + src/input/input_tsrist.cpp | 18 ++++++++-------- + src/input/input_tssrt.cpp | 18 ++++++++-------- + 19 files changed, 108 insertions(+), 116 deletions(-) + +diff --git a/src/input/input_aac.cpp b/src/input/input_aac.cpp +index a107bee6..cff14289 100644 +--- a/src/input/input_aac.cpp ++++ b/src/input/input_aac.cpp +@@ -65,7 +65,7 @@ namespace Mist{ + capa["source_match"] = "/*.aac"; + capa["source_file"] = "$source"; + capa["priority"] = 9; +- capa["codecs"][0u][1u].append("AAC"); ++ capa["codecs"]["audio"].append("AAC"); + thisTime = 0; + // init filePos at 1, else a 15 bit mismatch in expected frame size occurs + // dtsc.ccp +- line 215 +diff --git a/src/input/input_av.cpp b/src/input/input_av.cpp +index 94774cb9..aa7cd28c 100644 +--- a/src/input/input_av.cpp ++++ b/src/input/input_av.cpp +@@ -20,15 +20,13 @@ namespace Mist{ + capa["source_match"] = "/*"; + capa["source_file"] = "$source"; + capa["priority"] = 1; +- capa["codecs"][0u][0u].null(); +- capa["codecs"][0u][1u].null(); +- capa["codecs"][0u][2u].null(); ++ capa["codecs"].null(); + av_register_all(); + AVCodec *cInfo = 0; + while ((cInfo = av_codec_next(cInfo)) != 0){ +- if (cInfo->type == AVMEDIA_TYPE_VIDEO){capa["codecs"][0u][0u].append(cInfo->name);} +- if (cInfo->type == AVMEDIA_TYPE_AUDIO){capa["codecs"][0u][1u].append(cInfo->name);} +- if (cInfo->type == AVMEDIA_TYPE_SUBTITLE){capa["codecs"][0u][3u].append(cInfo->name);} ++ if (cInfo->type == AVMEDIA_TYPE_VIDEO){capa["codecs"]["video"].append(cInfo->name);} ++ if (cInfo->type == AVMEDIA_TYPE_AUDIO){capa["codecs"]["audio"].append(cInfo->name);} ++ if (cInfo->type == AVMEDIA_TYPE_SUBTITLE){capa["codecs"]["subtitle"].append(cInfo->name);} + } + } + +diff --git a/src/input/input_balancer.cpp b/src/input/input_balancer.cpp +index 36db5709..48997795 100644 +--- a/src/input/input_balancer.cpp ++++ b/src/input/input_balancer.cpp +@@ -80,9 +80,6 @@ namespace Mist{ + capa["optional"]["segmentsize"]["option"] = "--segment-size"; + capa["optional"]["segmentsize"]["type"] = "uint"; + capa["optional"]["segmentsize"]["default"] = 5000; +- capa["codecs"][0u][0u].append("*"); +- capa["codecs"][0u][1u].append("*"); +- capa["codecs"][0u][2u].append("*"); + } + + int inputBalancer::boot(int argc, char *argv[]){ +diff --git a/src/input/input_buffer.cpp b/src/input/input_buffer.cpp +index 534f9f6e..d1ccfbcf 100644 +--- a/src/input/input_buffer.cpp ++++ b/src/input/input_buffer.cpp +@@ -129,9 +129,6 @@ namespace Mist{ + "live media data. The push://[host][@password] style source allows all enabled protocols " + "that support push input to accept a push into MistServer, where you can accept incoming " + "streams from everyone, based on a set password, and/or use hostname/IP whitelisting."; +- capa["codecs"][0u][0u].append("*"); +- capa["codecs"][0u][1u].append("*"); +- capa["codecs"][0u][2u].append("*"); + bufferTime = 50000; + cutTime = 0; + segmentSize = 1900; +diff --git a/src/input/input_dtsc.cpp b/src/input/input_dtsc.cpp +index 381b59f1..bf7012db 100644 +--- a/src/input/input_dtsc.cpp ++++ b/src/input/input_dtsc.cpp +@@ -23,13 +23,13 @@ namespace Mist{ + capa["source_match"].append("dtsc://*"); + capa["always_match"].append("dtsc://*"); // can be said to always-on mode + capa["source_file"] = "$source"; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("H263"); +- capa["codecs"][0u][0u].append("VP6"); +- capa["codecs"][0u][0u].append("theora"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("MP3"); +- capa["codecs"][0u][1u].append("vorbis"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("H263"); ++ capa["codecs"]["video"].append("VP6"); ++ capa["codecs"]["video"].append("theora"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("MP3"); ++ capa["codecs"]["audio"].append("vorbis"); + + JSON::Value option; + option["arg"] = "integer"; +diff --git a/src/input/input_ebml.cpp b/src/input/input_ebml.cpp +index bcce5a77..958c1222 100644 +--- a/src/input/input_ebml.cpp ++++ b/src/input/input_ebml.cpp +@@ -19,26 +19,26 @@ namespace Mist{ + capa["always_match"].append("mkv-exec:*"); + capa["source_file"] = "$source"; + capa["priority"] = 9; +- capa["codecs"].append("H264"); +- capa["codecs"].append("HEVC"); +- capa["codecs"].append("VP8"); +- capa["codecs"].append("VP9"); +- capa["codecs"].append("AV1"); +- capa["codecs"].append("opus"); +- capa["codecs"].append("vorbis"); +- capa["codecs"].append("theora"); +- capa["codecs"].append("AAC"); +- capa["codecs"].append("PCM"); +- capa["codecs"].append("ALAW"); +- capa["codecs"].append("ULAW"); +- capa["codecs"].append("MP2"); +- capa["codecs"].append("MPEG2"); +- capa["codecs"].append("MP3"); +- capa["codecs"].append("AC3"); +- capa["codecs"].append("FLOAT"); +- capa["codecs"].append("DTS"); +- capa["codecs"].append("JSON"); +- capa["codecs"].append("subtitle"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("VP8"); ++ capa["codecs"]["video"].append("VP9"); ++ capa["codecs"]["video"].append("AV1"); ++ capa["codecs"]["video"].append("theora"); ++ capa["codecs"]["video"].append("MPEG2"); ++ capa["codecs"]["audio"].append("opus"); ++ capa["codecs"]["audio"].append("vorbis"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("PCM"); ++ capa["codecs"]["audio"].append("ALAW"); ++ capa["codecs"]["audio"].append("ULAW"); ++ capa["codecs"]["audio"].append("MP2"); ++ capa["codecs"]["audio"].append("MP3"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("FLOAT"); ++ capa["codecs"]["audio"].append("DTS"); ++ capa["codecs"]["metadata"].append("JSON"); ++ capa["codecs"]["subtitle"].append("subtitle"); + lastClusterBPos = 0; + lastClusterTime = 0; + bufferedPacks = 0; +diff --git a/src/input/input_flv.cpp b/src/input/input_flv.cpp +index d7399c23..82565119 100644 +--- a/src/input/input_flv.cpp ++++ b/src/input/input_flv.cpp +@@ -21,11 +21,11 @@ namespace Mist{ + capa["source_match"] = "/*.flv"; + capa["source_file"] = "$source"; + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("H263"); +- capa["codecs"][0u][0u].append("VP6"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("MP3"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("H263"); ++ capa["codecs"]["video"].append("VP6"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("MP3"); + } + + inputFLV::~inputFLV(){} +diff --git a/src/input/input_h264.cpp b/src/input/input_h264.cpp +index b9c72e47..f374c84f 100644 +--- a/src/input/input_h264.cpp ++++ b/src/input/input_h264.cpp +@@ -11,7 +11,7 @@ namespace Mist{ + // May be set to always-on mode + capa["always_match"].append("h264-exec:*"); + capa["priority"] = 0; +- capa["codecs"][0u][0u].append("H264"); ++ capa["codecs"]["video"].append("H264"); + frameCount = 0; + startTime = Util::bootMS(); + inputProcess = 0; +diff --git a/src/input/input_hls.cpp b/src/input/input_hls.cpp +index e51a951d..dc999eb4 100644 +--- a/src/input/input_hls.cpp ++++ b/src/input/input_hls.cpp +@@ -592,10 +592,10 @@ namespace Mist{ + capa["always_match"] = capa["source_match"]; + + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("MP3"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("MP3"); + + inFile = NULL; + } +diff --git a/src/input/input_ismv.cpp b/src/input/input_ismv.cpp +index 4e5a5cfa..71084955 100644 +--- a/src/input/input_ismv.cpp ++++ b/src/input/input_ismv.cpp +@@ -16,8 +16,8 @@ namespace Mist{ + capa["desc"] = "This input allows you to stream ISMV Video on Demand files."; + capa["source_match"] = "/*.ismv"; + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][1u].append("AAC"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["audio"].append("AAC"); + + inFile = 0; + } +diff --git a/src/input/input_mp3.cpp b/src/input/input_mp3.cpp +index 6bc656dd..4d757217 100644 +--- a/src/input/input_mp3.cpp ++++ b/src/input/input_mp3.cpp +@@ -19,7 +19,7 @@ namespace Mist{ + capa["source_match"] = "/*.mp3"; + capa["source_file"] = "$source"; + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("MP3"); ++ capa["codecs"]["audio"].append("MP3"); + timestamp = 0; + } + +diff --git a/src/input/input_mp4.cpp b/src/input/input_mp4.cpp +index f85911fb..5becc8c9 100644 +--- a/src/input/input_mp4.cpp ++++ b/src/input/input_mp4.cpp +@@ -169,13 +169,13 @@ namespace Mist{ + capa["source_match"].append("mp4:*"); + capa["source_file"] = "$source"; + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("HEVC"); +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("H263"); +- capa["codecs"][0u][0u].append("VP6"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("MP3"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("H263"); ++ capa["codecs"]["video"].append("VP6"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("MP3"); + readPos = 0; + } + +diff --git a/src/input/input_ogg.cpp b/src/input/input_ogg.cpp +index 7e262138..62380bf0 100644 +--- a/src/input/input_ogg.cpp ++++ b/src/input/input_ogg.cpp +@@ -38,9 +38,9 @@ namespace Mist{ + capa["desc"] = "This input allows streaming of OGG files as Video on Demand."; + capa["source_match"] = "/*.ogg"; + capa["source_file"] = "$source"; +- capa["codecs"][0u][0u].append("theora"); +- capa["codecs"][0u][1u].append("vorbis"); +- capa["codecs"][0u][1u].append("opus"); ++ capa["codecs"]["video"].append("theora"); ++ capa["codecs"]["audio"].append("vorbis"); ++ capa["codecs"]["audio"].append("opus"); + } + + bool inputOGG::checkArguments(){ +diff --git a/src/input/input_rtsp.cpp b/src/input/input_rtsp.cpp +index 25be6e23..59b25e1f 100644 +--- a/src/input/input_rtsp.cpp ++++ b/src/input/input_rtsp.cpp +@@ -42,19 +42,19 @@ namespace Mist{ + // These can/may be set to always-on mode + capa["always_match"].append("rtsp://*"); + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("HEVC"); +- capa["codecs"][0u][0u].append("MPEG2"); +- capa["codecs"][0u][0u].append("VP8"); +- capa["codecs"][0u][0u].append("VP9"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("MP3"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("ALAW"); +- capa["codecs"][0u][1u].append("ULAW"); +- capa["codecs"][0u][1u].append("PCM"); +- capa["codecs"][0u][1u].append("opus"); +- capa["codecs"][0u][1u].append("MP2"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("MPEG2"); ++ capa["codecs"]["video"].append("VP8"); ++ capa["codecs"]["video"].append("VP9"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("MP3"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("ALAW"); ++ capa["codecs"]["audio"].append("ULAW"); ++ capa["codecs"]["audio"].append("PCM"); ++ capa["codecs"]["audio"].append("opus"); ++ capa["codecs"]["audio"].append("MP2"); + + JSON::Value option; + option["arg"] = "integer"; +diff --git a/src/input/input_sdp.cpp b/src/input/input_sdp.cpp +index 0b8ddeb5..0072cbeb 100644 +--- a/src/input/input_sdp.cpp ++++ b/src/input/input_sdp.cpp +@@ -41,19 +41,19 @@ namespace Mist{ + capa["source_match"].append("*.sdp"); + capa["always_match"].append("*.sdp"); + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("HEVC"); +- capa["codecs"][0u][0u].append("MPEG2"); +- capa["codecs"][0u][0u].append("VP8"); +- capa["codecs"][0u][0u].append("VP9"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("MP3"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("ALAW"); +- capa["codecs"][0u][1u].append("ULAW"); +- capa["codecs"][0u][1u].append("PCM"); +- capa["codecs"][0u][1u].append("opus"); +- capa["codecs"][0u][1u].append("MP2"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("MPEG2"); ++ capa["codecs"]["video"].append("VP8"); ++ capa["codecs"]["video"].append("VP9"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("MP3"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("ALAW"); ++ capa["codecs"]["audio"].append("ULAW"); ++ capa["codecs"]["audio"].append("PCM"); ++ capa["codecs"]["audio"].append("opus"); ++ capa["codecs"]["audio"].append("MP2"); + + JSON::Value option; + option["arg"] = "integer"; +diff --git a/src/input/input_srt.cpp b/src/input/input_srt.cpp +index b89fa32e..22c1c3ee 100644 +--- a/src/input/input_srt.cpp ++++ b/src/input/input_srt.cpp +@@ -10,7 +10,7 @@ namespace Mist{ + capa["source_match"].append("/*.srt"); + capa["source_match"].append("/*.vtt"); + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("subtitle"); ++ capa["codecs"]["subtitle"].append("subtitle"); + } + + bool InputSrt::preRun(){ +diff --git a/src/input/input_ts.cpp b/src/input/input_ts.cpp +index e405e3b6..3bb02806 100644 +--- a/src/input/input_ts.cpp ++++ b/src/input/input_ts.cpp +@@ -191,14 +191,14 @@ namespace Mist{ + capa["incoming_push_url"] = "udp://$host:$port"; + capa["incoming_push_url_match"] = "tsudp://*"; + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("HEVC"); +- capa["codecs"][0u][0u].append("MPEG2"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("MP2"); +- capa["codecs"][0u][1u].append("opus"); +- capa["codecs"][1u][0u].append("rawts"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("MPEG2"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("MP2"); ++ capa["codecs"]["audio"].append("opus"); ++ capa["codecs"]["passthrough"].append("rawts"); + inFile = NULL; + inputProcess = 0; + isFinished = false; +diff --git a/src/input/input_tsrist.cpp b/src/input/input_tsrist.cpp +index df658da1..33f1155e 100644 +--- a/src/input/input_tsrist.cpp ++++ b/src/input/input_tsrist.cpp +@@ -92,15 +92,15 @@ namespace Mist{ + // These can/may be set to always-on mode + capa["always_match"].append("rist://*"); + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("HEVC"); +- capa["codecs"][0u][0u].append("MPEG2"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("MP3"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("MP2"); +- capa["codecs"][0u][1u].append("opus"); +- capa["codecs"][1u][0u].append("rawts"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("MPEG2"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("MP3"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("MP2"); ++ capa["codecs"]["audio"].append("opus"); ++ capa["codecs"]["passthrough"].append("rawts"); + + JSON::Value option; + option["arg"] = "integer"; +diff --git a/src/input/input_tssrt.cpp b/src/input/input_tssrt.cpp +index 8fef6d7d..28342930 100644 +--- a/src/input/input_tssrt.cpp ++++ b/src/input/input_tssrt.cpp +@@ -61,15 +61,15 @@ namespace Mist{ + capa["incoming_push_url"] = "srt://$host:$port"; + capa["incoming_push_url_match"] = "srt://*"; + capa["priority"] = 9; +- capa["codecs"][0u][0u].append("H264"); +- capa["codecs"][0u][0u].append("HEVC"); +- capa["codecs"][0u][0u].append("MPEG2"); +- capa["codecs"][0u][1u].append("AAC"); +- capa["codecs"][0u][1u].append("MP3"); +- capa["codecs"][0u][1u].append("AC3"); +- capa["codecs"][0u][1u].append("MP2"); +- capa["codecs"][0u][1u].append("opus"); +- capa["codecs"][1u][0u].append("rawts"); ++ capa["codecs"]["video"].append("H264"); ++ capa["codecs"]["video"].append("HEVC"); ++ capa["codecs"]["video"].append("MPEG2"); ++ capa["codecs"]["audio"].append("AAC"); ++ capa["codecs"]["audio"].append("MP3"); ++ capa["codecs"]["audio"].append("AC3"); ++ capa["codecs"]["audio"].append("MP2"); ++ capa["codecs"]["audio"].append("opus"); ++ capa["codecs"]["passthrough"].append("rawts"); + + JSON::Value option; + option["arg"] = "integer"; +-- +2.25.1 + + +From 067444306671531d3df3d39ad27d5df7cf14f3cc Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Mon, 10 Oct 2022 14:16:48 +0200 +Subject: [PATCH 30/38] Fix push outputs to use the correct remote addresses + +--- + lib/socket.cpp | 2 +- + lib/socket_srt.cpp | 1 + + src/output/output.cpp | 7 +++---- + src/output/output_cmaf.cpp | 1 + + src/output/output_rtmp.cpp | 1 + + src/output/output_ts.cpp | 1 + + src/output/output_tsrist.cpp | 1 + + 7 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/lib/socket.cpp b/lib/socket.cpp +index 47b2b6bd..aaefa2f2 100644 +--- a/lib/socket.cpp ++++ b/lib/socket.cpp +@@ -1207,7 +1207,7 @@ std::string Socket::Connection::getBinHost(){ + } + + /// Sets hostname for connection manually. +-/// Overwrites the detected host, thus possibily making it incorrect. ++/// Overwrites the detected host, thus possibly making it incorrect. + void Socket::Connection::setHost(std::string host){ + remotehost = host; + struct addrinfo *result, hints; +diff --git a/lib/socket_srt.cpp b/lib/socket_srt.cpp +index 6d1d5695..ac08dd8c 100644 +--- a/lib/socket_srt.cpp ++++ b/lib/socket_srt.cpp +@@ -208,6 +208,7 @@ namespace Socket{ + if (outgoing_port){setupAdapter("", outgoing_port);} + + sockaddr_in sa = createInetAddr(_host, _port); ++ memcpy(&remoteaddr, &sa, sizeof(sockaddr_in)); + sockaddr *psa = (sockaddr *)&sa; + + HIGH_MSG("Going to connect sock %d", sock); +diff --git a/src/output/output.cpp b/src/output/output.cpp +index d525b8ea..307c6b8c 100644 +--- a/src/output/output.cpp ++++ b/src/output/output.cpp +@@ -218,10 +218,9 @@ namespace Mist{ + + std::string Output::getConnectedBinHost(){ + if (!prevHost.size()){ +- if (myConn && myConn.getPureSocket() != -1){ +- prevHost = myConn.getBinHost(); +- } +- if (!prevHost.size()){prevHost.assign("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001", 16);} ++ MEDIUM_MSG("Setting prevHost to %s", getConnectedHost().c_str()); ++ prevHost = myConn.getBinHost(); ++ if (!prevHost.size()){prevHost.assign("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16);} + } + return prevHost; + } +diff --git a/src/output/output_cmaf.cpp b/src/output/output_cmaf.cpp +index eb7c87da..fa046db5 100644 +--- a/src/output/output_cmaf.cpp ++++ b/src/output/output_cmaf.cpp +@@ -93,6 +93,7 @@ namespace Mist{ + + INFO_MSG("About to push stream %s out. Host: %s, port: %" PRIu32 ", location: %s", + streamName.c_str(), pushUrl.host.c_str(), pushUrl.getPort(), pushUrl.path.c_str()); ++ myConn.setHost(pushUrl.host); + initialize(); + initialSeek(); + startPushOut(); +diff --git a/src/output/output_rtmp.cpp b/src/output/output_rtmp.cpp +index 23194f4a..41cf2191 100644 +--- a/src/output/output_rtmp.cpp ++++ b/src/output/output_rtmp.cpp +@@ -54,6 +54,7 @@ namespace Mist{ + } + INFO_MSG("About to push stream %s out. Host: %s, port: %d, app: %s, stream: %s", streamName.c_str(), + pushUrl.host.c_str(), pushUrl.getPort(), app.c_str(), streamOut.c_str()); ++ myConn.setHost(pushUrl.host); + initialize(); + initialSeek(); + startPushOut(""); +diff --git a/src/output/output_ts.cpp b/src/output/output_ts.cpp +index bf46663b..cec6eee4 100644 +--- a/src/output/output_ts.cpp ++++ b/src/output/output_ts.cpp +@@ -85,6 +85,7 @@ namespace Mist{ + } + } + pushSock.SetDestination(target.host, target.getPort()); ++ myConn.setHost(target.host); + pushing = false; + }else{ + //No push target? Check if this is a push input or pull output by waiting for data for 5s +diff --git a/src/output/output_tsrist.cpp b/src/output/output_tsrist.cpp +index 10b29673..a2861184 100644 +--- a/src/output/output_tsrist.cpp ++++ b/src/output/output_tsrist.cpp +@@ -130,6 +130,7 @@ namespace Mist{ + onFail("Failed to start RIST connection"); + return; + } ++ myConn.setHost(target.host); + wantRequest = false; + parseData = true; + initialize(); +-- +2.25.1 + + +From 8175ad6dd54a2d59393257d80fc96f7849bfbdcb Mon Sep 17 00:00:00 2001 +From: Thulinma <jaron@vietors.com> +Date: Thu, 13 Oct 2022 13:24:20 +0200 +Subject: [PATCH 31/38] Fix token handling when multiple sessions are + multiplexed over a single HTTP connection + +--- + src/output/output_http.cpp | 55 ++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 26 deletions(-) + +diff --git a/src/output/output_http.cpp b/src/output/output_http.cpp +index ed8fa33b..6d49c5c6 100644 +--- a/src/output/output_http.cpp ++++ b/src/output/output_http.cpp +@@ -218,6 +218,34 @@ namespace Mist{ + return; + } + ++ tkn.clear(); ++ // Read the session token ++ if (Comms::tknMode & 0x01){ ++ // Get session token from the request url ++ if (H.GetVar("tkn") != ""){ ++ tkn = H.GetVar("tkn"); ++ } else if (H.GetVar("sid") != ""){ ++ tkn = H.GetVar("sid"); ++ } else if (H.GetVar("sessId") != ""){ ++ tkn = H.GetVar("sessId"); ++ } ++ } ++ if ((Comms::tknMode & 0x02) && !tkn.size()){ ++ // Get session token from the request cookie ++ std::map<std::string, std::string> storage; ++ const std::string koekjes = H.GetHeader("Cookie"); ++ HTTP::parseVars(koekjes, storage, "; "); ++ if (storage.count("tkn")){ ++ tkn = storage.at("tkn"); ++ } ++ } ++ // Generate a session token if it is being sent as a cookie or url parameter and we couldn't read one ++ if (!tkn.size() && Comms::tknMode > 3){ ++ const std::string newTkn = UA + JSON::Value(getpid()).asString(); ++ tkn = JSON::Value(checksum::crc32(0, newTkn.data(), newTkn.size())).asString(); ++ HIGH_MSG("Generated tkn '%s'", tkn.c_str()); ++ } ++ + //Check if we need to change binary and/or reconnect + if (handler != capa["name"].asStringRef() || H.GetVar("stream") != streamName || (statComm && (statComm.getHost() != getConnectedBinHost() || statComm.getTkn() != tkn))){ + MEDIUM_MSG("Switching from %s (%s) to %s (%s)", capa["name"].asStringRef().c_str(), +@@ -270,32 +298,7 @@ namespace Mist{ + realTime = 0; + } + } +- // Read the session token +- if (Comms::tknMode & 0x01){ +- // Get session token from the request url +- if (H.GetVar("tkn") != ""){ +- tkn = H.GetVar("tkn"); +- } else if (H.GetVar("sid") != ""){ +- tkn = H.GetVar("sid"); +- } else if (H.GetVar("sessId") != ""){ +- tkn = H.GetVar("sessId"); +- } +- } +- if ((Comms::tknMode & 0x02) && !tkn.size()){ +- // Get session token from the request cookie +- std::map<std::string, std::string> storage; +- const std::string koekjes = H.GetHeader("Cookie"); +- HTTP::parseVars(koekjes, storage, "; "); +- if (storage.count("tkn")){ +- tkn = storage.at("tkn"); +- } +- } +- // Generate a session token if it is being sent as a cookie or url parameter and we couldn't read one +- if (!tkn.size() && Comms::tknMode > 3){ +- const std::string newTkn = UA + JSON::Value(getpid()).asString(); +- tkn = JSON::Value(checksum::crc32(0, newTkn.data(), newTkn.size())).asString(); +- HIGH_MSG("Generated tkn '%s'", tkn.c_str()); +- } ++ + // Handle upgrade to websocket if the output supports it + std::string upgradeHeader = H.GetHeader("Upgrade"); + Util::stringToLower(upgradeHeader); +-- +2.25.1 + + +From fb6de1742bc04cf53ef49008166cfecc36b5e96c Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Tue, 20 Sep 2022 15:40:08 +0200 +Subject: [PATCH 32/38] Add building via meson + +--- + generated/make_html.cpp | 39 +++++++++ + generated/meson.build | 40 ++++++++++ + lib/meson.build | 135 +++++++++++++++++++++++++++++++ + lsp/meson.build | 26 ++++++ + meson.build | 157 +++++++++++++++++++++++++++++++++++++ + meson_options.txt | 30 +++++++ + mist/meson.build | 5 ++ + src/analysers/meson.build | 39 +++++++++ + src/controller/meson.build | 21 +++++ + src/input/meson.build | 85 ++++++++++++++++++++ + src/meson.build | 19 +++++ + src/output/meson.build | 133 +++++++++++++++++++++++++++++++ + src/process/meson.build | 50 ++++++++++++ + src/utils/meson.build | 28 +++++++ + test/meson.build | 18 +++++ + 15 files changed, 825 insertions(+) + create mode 100644 generated/make_html.cpp + create mode 100644 generated/meson.build + create mode 100644 lib/meson.build + create mode 100644 lsp/meson.build + create mode 100644 meson.build + create mode 100644 meson_options.txt + create mode 100644 mist/meson.build + create mode 100644 src/analysers/meson.build + create mode 100644 src/controller/meson.build + create mode 100644 src/input/meson.build + create mode 100644 src/meson.build + create mode 100644 src/output/meson.build + create mode 100644 src/process/meson.build + create mode 100644 src/utils/meson.build + create mode 100644 test/meson.build + +diff --git a/generated/make_html.cpp b/generated/make_html.cpp +new file mode 100644 +index 00000000..0d986eb6 +--- /dev/null ++++ b/generated/make_html.cpp +@@ -0,0 +1,39 @@ ++#include <cstdlib> ++#include <ios> ++#include <iostream> ++#include <fstream> ++#include <ostream> ++ ++int main(int argc, char* argv[]) { ++ if (argc < 6) { ++ std::cerr << "ERROR EXPECTED MORE FILES" << std::endl; ++ return 1; ++ } ++ ++ std::ofstream output(argv[1]); ++ ++ std::ifstream header(argv[2]); ++ std::ifstream css(argv[3]); ++ std::ifstream footer(argv[4]); ++ ++ if (!header.is_open() || !css.is_open() || !footer.is_open()) { ++ std::cerr << "ERROR Couldn't open file" << std::endl; ++ return 1; ++ } ++ ++ output << header.rdbuf(); ++ output << "<script>"; ++ for (int i = 5; i < argc; i++) { ++ std::ifstream script(argv[i]); ++ if (!script.is_open()) { ++ std::cerr << "ERROR Couldn't open file" << std::endl; ++ return 1; ++ } ++ output << script.rdbuf(); ++ } ++ output << "</script>"; ++ output << "<style>" << css.rdbuf() << "</style>"; ++ output << footer.rdbuf(); ++ std::flush(output); ++ return 0; ++} +\ No newline at end of file +diff --git a/generated/meson.build b/generated/meson.build +new file mode 100644 +index 00000000..30296c35 +--- /dev/null ++++ b/generated/meson.build +@@ -0,0 +1,40 @@ ++ ++sourcery = executable('sourcery', '../src/sourcery.cpp', native: true) ++ ++make_html = executable('make_html', 'make_html.cpp', native: true) ++ ++gen_html = custom_target('gen_html', output: 'server.html', input: html_files, command: [make_html, '@OUTPUT@', '@INPUT@']) ++ ++embed_files = [ ++ {'infile': '../embed/min/player.js', 'variable': 'player_js', 'outfile': 'player.js.h'}, ++ {'infile': '../embed/min/wrappers/html5.js', 'variable': 'html5_js', 'outfile': 'html5.js.h'}, ++ {'infile': '../embed/min/wrappers/flash_strobe.js', 'variable': 'flash_strobe_js', 'outfile': 'flash_strobe.js.h'}, ++ {'infile': '../embed/min/wrappers/dashjs.js', 'variable': 'dash_js', 'outfile': 'dashjs.js.h'}, ++ {'infile': '../embed/min/wrappers/videojs.js', 'variable': 'video_js', 'outfile': 'videojs.js.h'}, ++ {'infile': '../embed/min/wrappers/webrtc.js', 'variable': 'webrtc_js', 'outfile': 'webrtc.js.h'}, ++ {'infile': '../embed/min/wrappers/mews.js', 'variable': 'mews_js', 'outfile': 'mews.js.h'}, ++ {'infile': '../embed/min/wrappers/flv.js', 'variable': 'flv_js', 'outfile': 'flv.js.h'}, ++ {'infile': '../embed/min/wrappers/hlsjs.js', 'variable': 'hlsjs_js', 'outfile': 'hlsjs.js.h'}, ++ {'infile': '../embed/min/wrappers/rawws.js', 'variable': 'rawws_js', 'outfile': 'rawws.js.h'}, ++ {'infile': '../embed/players/dash.js.license.js', 'variable': 'player_dash_lic_js','outfile': 'player_dash_lic.js.h'}, ++ {'infile': '../embed/players/dash.all.min.js', 'variable': 'player_dash_js', 'outfile': 'player_dash.js.h'}, ++ {'infile': '../embed/players/video.min.js', 'variable': 'player_video_js', 'outfile': 'player_video.js.h'}, ++ {'infile': '../embed/players/webrtc.js', 'variable': 'player_webrtc_js', 'outfile': 'player_webrtc.js.h'}, ++ {'infile': '../embed/players/flv.min.js', 'variable': 'player_flv_js', 'outfile': 'player_flv.js.h'}, ++ {'infile': '../embed/players/hls.js', 'variable': 'player_hlsjs_js', 'outfile': 'player_hlsjs.js.h'}, ++ {'infile': '../embed/players/libde265.min.js', 'variable': 'player_libde265_js','outfile': 'player_libde265.js.h'}, ++ {'infile': '../embed/min/skins/default.css', 'variable': 'skin_default_css', 'outfile': 'skin_default.css.h'}, ++ {'infile': '../embed/min/skins/dev.css', 'variable': 'skin_dev_css', 'outfile': 'skin_dev.css.h'}, ++ {'infile': '../embed/skins/video-js.css', 'variable': 'skin_videojs_css', 'outfile': 'skin_videojs.css.h'}, ++ {'infile': '../src/output/noffmpeg.jpg', 'variable': 'noffmpeg', 'outfile': 'noffmpeg.h'}, ++ {'infile': '../src/output/noh264.jpg', 'variable': 'noh264', 'outfile': 'noh264.h'}, ++] ++ ++embed_tgts = [] ++ ++foreach e : embed_files ++ embed_tgts += custom_target('embed_'+e.get('outfile'), output: e.get('outfile'), input: e.get('infile'), command: [sourcery, '@INPUT@', e.get('variable'), '@OUTPUT@']) ++endforeach ++ ++ ++server_html = custom_target('embed_server.html', output: 'server.html.h', input: gen_html, command: [sourcery, '@INPUT@', 'server_html', '@OUTPUT@']) +diff --git a/lib/meson.build b/lib/meson.build +new file mode 100644 +index 00000000..02a40350 +--- /dev/null ++++ b/lib/meson.build +@@ -0,0 +1,135 @@ ++ ++headers = [ ++ 'adts.h', ++ 'amf.h', ++ 'auth.h', ++ 'encode.h', ++ 'bitfields.h', ++ 'bitstream.h', ++ 'certificate.h', ++ 'checksum.h', ++ 'cmaf.h', ++ 'comms.h', ++ 'config.h', ++ 'defines.h', ++ 'dtls_srtp_handshake.h', ++ 'dtsc.h', ++ 'encryption.h', ++ 'flv_tag.h', ++ 'h264.h', ++ 'h265.h', ++ 'hls_support.h', ++ 'http_parser.h', ++ 'downloader.h', ++ 'json.h', ++ 'langcodes.h', ++ 'mp4_adobe.h', ++ 'mp4_dash.h', ++ 'mp4_encryption.h', ++ 'mp4_generic.h', ++ 'mp4.h', ++ 'mp4_ms.h', ++ 'mpeg.h', ++ 'nal.h', ++ 'ogg.h', ++ 'procs.h', ++ 'rtmpchunks.h', ++ 'rtp_fec.h', ++ 'rtp.h', ++ 'sdp.h', ++ 'sdp_media.h', ++ 'shared_memory.h', ++ 'socket.h', ++ 'srtp.h', ++ 'stream.h', ++ 'stun.h', ++ 'theora.h', ++ 'timing.h', ++ 'tinythread.h', ++ 'ts_packet.h', ++ 'ts_stream.h', ++ 'util.h', ++ 'vorbis.h', ++ 'triggers.h', ++ 'opus.h', ++ 'riff.h', ++ 'ebml.h', ++ 'ebml_socketglue.h', ++ 'websocket.h', ++ 'url.h', ++ 'urireader.h', ++] ++ ++if have_srt ++ headers += 'socket_srt.h' ++endif ++ ++install_headers(headers, subdir: 'mist') ++ ++extra_code = [] ++ ++if usessl ++ extra_code += ['dtls_srtp_handshake.cpp', 'stun.cpp', 'certificate.cpp', 'encryption.cpp', 'srtp.cpp',] ++endif ++ ++libmist = library('mist', ++ 'adts.cpp', ++ 'amf.cpp', ++ 'auth.cpp', ++ 'encode.cpp', ++ 'bitfields.cpp', ++ 'bitstream.cpp', ++ 'cmaf.cpp', ++ 'comms.cpp', ++ 'config.cpp', ++ 'dtsc.cpp', ++ 'flv_tag.cpp', ++ 'h264.cpp', ++ 'h265.cpp', ++ 'hls_support.cpp', ++ 'http_parser.cpp', ++ 'downloader.cpp', ++ 'json.cpp', ++ 'langcodes.cpp', ++ 'mp4_adobe.cpp', ++ 'mp4.cpp', ++ 'mp4_dash.cpp', ++ 'mp4_encryption.cpp', ++ 'mp4_generic.cpp', ++ 'mp4_ms.cpp', ++ 'mpeg.cpp', ++ 'nal.cpp', ++ 'ogg.cpp', ++ 'procs.cpp', ++ 'rtmpchunks.cpp', ++ 'rtp_fec.cpp', ++ 'rtp.cpp', ++ 'sdp.cpp', ++ 'sdp_media.cpp', ++ 'shared_memory.cpp', ++ 'socket.cpp', ++ 'stream.cpp', ++ 'theora.cpp', ++ 'timing.cpp', ++ 'tinythread.cpp', ++ 'ts_packet.cpp', ++ 'ts_stream.cpp', ++ 'util.cpp', ++ 'vorbis.cpp', ++ 'triggers.cpp', ++ 'opus.cpp', ++ 'riff.cpp', ++ 'ebml.cpp', ++ 'ebml_socketglue.cpp', ++ 'url.cpp', ++ 'urireader.cpp', ++ 'websocket.cpp', ++ extra_code, ++ include_directories: incroot, ++ dependencies: ssl_deps, ++ install: true, ++) ++ ++if have_srt ++ libmist_srt = library('mist_srt', 'socket_srt.cpp', include_directories: incroot, link_with: libmist, dependencies: libsrt, install: true) ++endif +\ No newline at end of file +diff --git a/lsp/meson.build b/lsp/meson.build +new file mode 100644 +index 00000000..e5a6b36a +--- /dev/null ++++ b/lsp/meson.build +@@ -0,0 +1,26 @@ ++minified = files('minified.js') ++ ++if get_option('LSP_MINIFY') ++ java = find_program('java', required: true) ++ ++ closure_compiler = files('closure-compiler.jar') ++ ++ minified = custom_target('lsp_gen_minified',output: 'minified.js', input: ['plugins/md5.js', 'plugins/cattablesort.js', 'mist.js'], command: [java, '-jar', closure_compiler, '--warning_level', 'QUIET', '@INPUT@'], capture: true) ++endif ++ ++html_list = ['header.html', ++ 'main.css', ++ 'footer.html', ++ 'plugins/jquery.js', ++ 'plugins/jquery.flot.min.js', ++ 'plugins/jquery.flot.time.min.js', ++ 'plugins/jquery.qrcode.min.js', ++ ] ++ ++html_files = files(html_list) ++html_files += minified ++ ++if not get_option('NOGA') ++ html_files += files('analytics.js') ++endif ++ +diff --git a/meson.build b/meson.build +new file mode 100644 +index 00000000..38bd29c3 +--- /dev/null ++++ b/meson.build +@@ -0,0 +1,157 @@ ++project('mistserver', 'cpp', default_options: ['cpp_std=gnu++03']) ++ ++ccpp = meson.get_compiler('cpp') ++ ++incroot = include_directories('.') ++ ++release = get_option('RELEASE') ++if release.contains('DEFAULT') ++ release = 'Generic_'+target_machine.cpu_family() ++endif ++release = release.strip() ++ ++rv = run_command('git', 'describe', '--tags', check: false) ++version = rv.stdout().strip() ++if rv.returncode() != 0 ++ version = 'Unknown' ++endif ++ ++add_project_arguments(['-funsigned-char', '-D_LARGEFILE_SOURCE','-Wno-sign-compare', '-Wparentheses', '-Wno-non-virtual-dtor', '-Wno-strict-aliasing'], language: 'cpp') ++ ++string_opt = '-D@0@="@1@"' ++int_opt = '-D@0@=@1@' ++ ++option_defines = [ ++ string_opt.format('APPNAME', get_option('APPNAME')), ++ int_opt.format('DEBUG', get_option('DEBUG')), ++ string_opt.format('RELEASE' ,release), ++ string_opt.format('PACKAGE_VERSION' ,version), ++ int_opt.format('SHM_DATASIZE', get_option('DATASIZE')), ++ int_opt.format('STAT_CUTOFF', get_option('STAT_CUTOFF')), ++ int_opt.format('STATS_DELAY', get_option('STATS_DELAY')), ++ string_opt.format('UDP_API_HOST' ,get_option('UDP_API_HOST')), ++ int_opt.format('UDP_API_PORT', get_option('UDP_API_PORT')), ++] ++ ++if not get_option('NOSHM') ++ option_defines += '-DSHM_ENABLED=1' ++else ++ message('Shared memory use is turned OFF') ++endif ++ ++if not get_option('FILLER_DATA').contains('DEFAULT') and not get_option('SHARED_SECRET').contains('DEFAULT') and not get_option('SUPER_SECRET').contains('DEFAULT') ++ option_defines += [ ++ string_opt.format('FILLER_DATA' ,get_option('FILLER_DATA')), ++ string_opt.format('SHARED_SECRET' ,get_option('SHARED_SECRET')), ++ string_opt.format('SUPER_SECRET',get_option('SUPER_SECRET')), ++ ] ++endif ++ ++#Since a lot of checks in the code are in #ifdef format (vs simple #if) we unfortunately have to do a lot of conditionals here.. otherwise it would be a one liner like this: ++#option_defines += int_opt.format('GEOIP', get_option('GEOIP').to_int()) ++if get_option('GEOIP') ++ option_defines += '-DGEOIP=1' ++endif ++ ++usessl = true ++if get_option('NOSSL') ++ message('SSL/TLS support is turned OFF') ++ usessl = false ++ option_defines += '-DNOSSL=1' ++else ++ option_defines += '-DSSL=1' ++endif ++ ++if not get_option('NOUPDATE') ++ option_defines += '-DUPDATER=1' ++endif ++ ++if not get_option('PERPETUAL') ++ option_defines += '-DLICENSING=1' ++endif ++ ++if get_option('NOAUTH') ++ option_defines += '-DNOAUTH=1' ++endif ++ ++if get_option('KILLONEXIT') ++ option_defines += '-DKILLONEXIT=true' ++endif ++ ++if not get_option('DISKSERIAL').contains('DEFAULT') ++ option_defines +=string_opt.format('DISKSERIAL',get_option('DISKSERIAL')) ++endif ++ ++if get_option('WITH_THREADNAMES') ++ option_defines += '-DWITH_THREADNAMES=1' ++endif ++ ++if get_option('NOCRASHCHECK') ++ option_defines += '-DNOCRASHCHECK=1' ++endif ++ ++if get_option('NOLLHLS') ++ option_defines += '-DNOLLHLS=1' ++endif ++ ++message('Builing release @0@ for version @1@ @ debug level @2@'.format(release, version, get_option('DEBUG'))) ++ ++libsrt = false ++if not get_option('NOSRT') ++ libsrt = dependency('srt', required: false) ++endif ++librist = false ++if not get_option('NORIST') ++ librist = dependency('librist', required: false) ++endif ++ ++ssl_deps = [] ++ ++have_librist = not get_option('NORIST') and librist.found() ++have_srt = not get_option('NOSRT') and libsrt.found() ++ ++if usessl ++ mbedtls = ccpp.find_library('mbedtls') ++ mbedx509 = ccpp.find_library('mbedx509') ++ mbedcrypto = ccpp.find_library('mbedcrypto') ++ srtp2 = dependency('libsrtp2') ++ ssl_deps = [mbedtls, mbedx509, mbedcrypto, srtp2] ++endif ++ ++add_project_arguments(option_defines, language: 'cpp') ++ ++executables = [] ++ ++subdir('lib') ++subdir('mist')#This "generates" the headers.. ++subdir('lsp') ++subdir('generated') ++subdir('src') ++subdir('test') ++ ++exec_tgts = [] ++ ++##This makes sure all (installable) executables are build in top level directory ++##Needed to make testing simple, since MistController expects it's binaries to be next to it ++foreach exec : executables ++ exec_tgts += executable( ++ exec.get('name'), ++ exec.get('sources'), ++ link_with: exec.get('link'), ++ dependencies: exec.get('deps'), ++ cpp_args: exec.get('defines'), ++ install: true, ++ ) ++endforeach ++ ++doxygen = find_program('doxygen', required: false) ++if doxygen.found() ++ doxyfile = configure_file(output: 'Doxyfile', input: 'Doxyfile.in', configuration: { ++ 'PACKAGE_VERSION': version, ++ 'RELEASE' : release, ++ }) ++ layout = custom_target('copy_layout', input: 'DoxygenLayout.xml', output: 'DoxygenLayout.xml', command: ['cp', '@INPUT@', '@OUTPUT@']) ++ run_target('docs', command: [doxygen, doxyfile], depends: layout) ++endif ++ ++#docs = custom_target('docs', ) +diff --git a/meson_options.txt b/meson_options.txt +new file mode 100644 +index 00000000..23600e85 +--- /dev/null ++++ b/meson_options.txt +@@ -0,0 +1,30 @@ ++option('NOSHM', description: 'Disabled shared memory (falling back to shared temporary files)', type : 'boolean', value : false) ++option('GEOIP', description: 'Enable GeoIP capabilities (deprecated)', type : 'boolean', value : false) ++option('NOSSL', description: 'Disable SSL/TLS support', type : 'boolean', value : false) ++option('NOUPDATE', description: 'Disable the updater', type : 'boolean', value : false) ++option('PERPETUAL', description: 'Disable the licensing system', type : 'boolean', value : false) ++option('NOAUTH', description: 'Disable API authentication entirely (insecure!)', type : 'boolean', value : false) ++option('KILLONEXIT', description: 'Kill all processes on exit, ensuring nothing is running anymore (disables rolling restart/update support)', type : 'boolean', value : false) ++option('WITH_THREADNAMES', description: 'Enable fancy names for threads (not supported on all platforms)', type : 'boolean', value : false) ++option('NOCRASHCHECK', description: 'Disables the crash check in the controller stats and input userpages. Prevents killing processes that are stalled/stuck.', type : 'boolean', value : false) ++option('NOLLHLS', description: 'Disable LLHLS', type : 'boolean', value : false) ++option('FILLER_DATA', type: 'string', value: 'DEFAULT') ++option('SHARED_SECRET', type: 'string', value: 'DEFAULT') ++option('SUPER_SECRET', type: 'string', value: 'DEFAULT') ++option('UDP_API_HOST', type: 'string', value: 'localhost') ++option('UDP_API_PORT', type: 'integer', value: 4242) ++option('DISKSERIAL', description: 'Lock application to given disk serial number', type: 'string', value: 'DEFAULT') ++option('STATS_DELAY', type: 'integer', value: 15) ++option('APPNAME', description: 'Name of the application', type: 'string', value: 'MistServer') ++option('DATASIZE', type: 'integer', value: 40) ++option('STAT_CUTOFF', type: 'integer', value: 600) ++option('NORIST', description: 'Disable building RIST support, regardless of library being present (by default RIST is enabled if libraries are installed)', type : 'boolean', value : false) ++option('NOSRT', description: 'Disable building SRT support, regardless of library being present (by default SRT is enabled if libraries are installed)', type : 'boolean', value : false) ++option('RELEASE', type: 'string', value: 'DEFAULT') ++option('DEBUG', type: 'integer', value: 4) ++option('NOGA', description: 'Disables Google Analytics entirely in the LSP', type: 'boolean', value: false) ++option('LOAD_BALANCE', description: 'Build the load balancer', type: 'boolean', value: false) ++option('WITH_AV', description: 'Build a generic libav-based input (not distributable!)', type: 'boolean', value: false) ++option('WITH_JPG', description: 'Build JPG thumbnailer output support', type: 'boolean', value: false) ++option('WITH_SANITY', description: 'Enable MistOutSanityCheck output for testing purposes', type: 'boolean', value: false) ++option('LSP_MINIFY', description: 'Try to minify LSP JS via java closure-compiler, generally not needed unless changing JS code', type: 'boolean', value: false) +\ No newline at end of file +diff --git a/mist/meson.build b/mist/meson.build +new file mode 100644 +index 00000000..fe6c5863 +--- /dev/null ++++ b/mist/meson.build +@@ -0,0 +1,5 @@ ++header_tgts = [] ++ ++foreach header : headers ++ header_tgts += custom_target('copy'+header, input: join_paths('../lib', header), output: header, command: ['cp', '@INPUT@', '@OUTPUT@']) ++endforeach +\ No newline at end of file +diff --git a/src/analysers/meson.build b/src/analysers/meson.build +new file mode 100644 +index 00000000..64f74271 +--- /dev/null ++++ b/src/analysers/meson.build +@@ -0,0 +1,39 @@ ++ ++analysers = [ ++ {'name': 'RTMP', 'format': 'rtmp'}, ++ {'name': 'FLV', 'format': 'flv'}, ++ {'name': 'DTSC', 'format': 'dtsc'}, ++ {'name': 'OGG', 'format': 'ogg'}, ++ {'name': 'EBML', 'format': 'ebml'}, ++ {'name': 'TS', 'format': 'ts'}, ++ {'name': 'MP4', 'format': 'mp4'}, ++ {'name': 'H264', 'format': 'h264'}, ++ {'name': 'HLS', 'format': 'hls'}, ++ {'name': 'RIFF', 'format': 'riff'}, ++ {'name': 'RTSP', 'format': 'rtsp'}, ++] ++ ++foreach analyser : analysers ++ executables += { 'name': 'MistAnalyser'+analyser.get('name'), ++ 'sources' : [ ++ files('mist_analyse.cpp', ++ 'analyser.cpp', ++ 'analyser_'+analyser.get('format')+'.cpp'), ++ header_tgts, ++ ], ++ 'link': libmist, ++ 'defines': [ ++ string_opt.format('ANALYSERHEADER', 'analyser_'+analyser.get('format')+'.h'), ++ '-DANALYSERTYPE=Analyser'+analyser.get('name') ++ ], ++ 'deps': [] ++ } ++endforeach ++ ++executables += { ++ 'name': 'MistTranslateH264', ++ 'sources' : [files('h264_translate.cpp'), header_tgts], ++ 'link': libmist, ++ 'defines': [], ++ 'deps' : [] ++} +\ No newline at end of file +diff --git a/src/controller/meson.build b/src/controller/meson.build +new file mode 100644 +index 00000000..757dcd3d +--- /dev/null ++++ b/src/controller/meson.build +@@ -0,0 +1,21 @@ ++ ++executables += { ++ 'name': 'MistController', ++ 'sources' : [ ++ files( 'controller.cpp', ++ 'controller_updater.cpp', ++ 'controller_streams.cpp', ++ 'controller_storage.cpp', ++ 'controller_connectors.cpp', ++ 'controller_statistics.cpp', ++ 'controller_limits.cpp', ++ 'controller_capabilities.cpp', ++ 'controller_uplink.cpp', ++ 'controller_api.cpp', ++ 'controller_push.cpp'), ++ header_tgts, ++ server_html], ++ 'link': libmist, ++ 'defines': [], ++ 'deps' : [] ++} +\ No newline at end of file +diff --git a/src/input/meson.build b/src/input/meson.build +new file mode 100644 +index 00000000..02d6891c +--- /dev/null ++++ b/src/input/meson.build +@@ -0,0 +1,85 @@ ++inputs = [ ++ {'name' : 'HLS', 'format' : 'hls'}, ++ {'name' : 'DTSC', 'format' : 'dtsc'}, ++ {'name' : 'MP3', 'format' : 'mp3'}, ++ {'name' : 'FLV', 'format' : 'flv'}, ++ {'name' : 'OGG', 'format' : 'ogg'}, ++ {'name' : 'Buffer', 'format' : 'buffer'}, ++ {'name' : 'H264', 'format' : 'h264'}, ++ {'name' : 'EBML', 'format' : 'ebml'}, ++ {'name' : 'ISMV', 'format' : 'ismv'}, ++ {'name' : 'MP4', 'format' : 'mp4'}, ++ {'name' : 'TS', 'format' : 'ts'}, ++ {'name' : 'Folder', 'format' : 'folder'}, ++ {'name' : 'Playlist', 'format' : 'playlist'}, ++ {'name' : 'Balancer', 'format' : 'balancer'}, ++ {'name' : 'RTSP', 'format' : 'rtsp'}, ++ {'name' : 'SRT', 'format' : 'srt'}, ++ {'name' : 'SDP', 'format' : 'sdp'}, ++ #{'name' : 'AAC', 'format' : 'aac'}, ++] ++ ++#Referenced by process targets ++input_ebml_cpp = files('input_ebml.cpp') ++input_cpp = files('input.cpp') ++ ++if have_librist ++ inputs += {'name' : 'TSRIST', 'format' : 'tsrist', 'extra' : 'with_rist'} ++endif ++ ++if have_srt ++ inputs += {'name' : 'TSSRT', 'format' : 'tssrt', 'extra' : 'with_srt'} ++endif ++ ++av_libs = [] ++ ++if get_option('WITH_AV') ++ inputs += {'name' : 'AV', 'format' : 'av'} ++ av_libs = [ ++ dependency('libavformat'), ++ dependency('libavcodec'), ++ dependency('libavutil'), ++ ] ++endif ++ ++inputs_tgts = [] ++ ++foreach input : inputs ++ link_libs = [libmist] ++ deps = [] ++ ++ if input.has_key('extra') ++ if input.get('extra').contains('with_rist') ++ deps += librist ++ endif ++ if input.get('extra').contains('with_srt') ++ link_libs += libmist_srt ++ deps += libsrt ++ endif ++ endif ++ if input.get('name').contains('AV') ++ deps += av_libs ++ endif ++ if input.get('name').contains('HLS') ++ deps += ssl_deps ++ endif ++ ++ executables += { ++ 'name' : 'MistIn'+input.get('name'), ++ 'sources' : [ ++ files( ++ 'mist_in.cpp', ++ 'input.cpp', ++ 'input_'+input.get('format')+'.cpp', ++ ), ++ io_cpp, ++ header_tgts ++ ], ++ 'link' : link_libs, ++ 'deps' : deps, ++ 'inc': [], ++ 'defines': [ ++ string_opt.format('INPUTTYPE', 'input_'+input.get('format')+'.h') ++ ] ++ } ++endforeach +diff --git a/src/meson.build b/src/meson.build +new file mode 100644 +index 00000000..af2730d7 +--- /dev/null ++++ b/src/meson.build +@@ -0,0 +1,19 @@ ++io_cpp = files('io.cpp') ++ ++subdir('analysers') ++subdir('utils') ++subdir('input') ++subdir('output') ++subdir('process') ++subdir('controller') ++ ++executables += { ++ 'name': 'relaccxsampler', ++ 'sources': [ ++ files('relaccxsampler.cpp'), ++ header_tgts, ++ ], ++ 'link': libmist, ++ 'deps': [], ++ 'defines': [], ++} +\ No newline at end of file +diff --git a/src/output/meson.build b/src/output/meson.build +new file mode 100644 +index 00000000..aa46fac3 +--- /dev/null ++++ b/src/output/meson.build +@@ -0,0 +1,133 @@ ++outputs = [ ++ {'name' : 'RTMP', 'format' : 'rtmp'}, ++ {'name' : 'DTSC', 'format' : 'dtsc'}, ++ {'name' : 'OGG', 'format' : 'ogg', 'extra': ['http']}, ++ {'name' : 'FLV', 'format' : 'flv', 'extra': ['http'] }, ++ {'name' : 'HTTPMinimalServer', 'format' : 'http_minimalserver', 'extra': ['http']}, ++ {'name' : 'MP4', 'format' : 'mp4', 'extra': ['http']}, ++ {'name' : 'AAC', 'format' : 'aac', 'extra': ['http']}, ++ {'name' : 'MP3', 'format' : 'mp3', 'extra': ['http']}, ++ {'name' : 'H264', 'format' : 'h264', 'extra': ['http']}, ++ {'name' : 'HDS', 'format' : 'hds', 'extra': ['http']}, ++ {'name' : 'SRT', 'format' : 'srt', 'extra': ['http']}, ++ {'name' : 'JSON', 'format' : 'json', 'extra': ['http']}, ++ {'name' : 'TS', 'format' : 'ts', 'extra': ['ts']}, ++ {'name' : 'HTTPTS', 'format' : 'httpts', 'extra': ['http', 'ts']}, ++ {'name' : 'HLS', 'format' : 'hls', 'extra': ['http', 'ts']}, ++ {'name' : 'CMAF', 'format' : 'cmaf', 'extra': ['http']}, ++ {'name' : 'EBML', 'format' : 'ebml', 'extra': ['http']}, ++ {'name' : 'RTSP', 'format' : 'rtsp'}, ++ {'name' : 'WAV', 'format' : 'wav', 'extra': ['http']}, ++ {'name' : 'SDP', 'format' : 'sdp', 'extra': ['http']}, ++] ++ ++#Referenced by targets in process ++output_ebml_cpp = files('output_ebml.cpp') ++output_http_cpp = files('output_http.cpp') ++output_ts_base_cpp = files('output_ts_base.cpp') ++output_cpp = files('output.cpp') ++ ++if have_librist ++ outputs += {'name' : 'TSRIST', 'format' : 'tsrist', 'extra': ['ts', 'debased', 'with_rist']} ++endif ++ ++if have_srt ++ outputs += {'name' : 'TSSRT', 'format' : 'tssrt', 'extra': ['ts', 'debased', 'with_srt']} ++endif ++ ++if get_option('WITH_JPG') ++ outputs += {'name' : 'JPG', 'format' : 'jpg', 'extra': ['http','jpg']} ++endif ++ ++if usessl ++ outputs += [ ++ {'name' : 'HTTPS', 'format' : 'https'}, ++ {'name' : 'WebRTC', 'format' : 'webrtc', 'extra': ['http','jpg']} ++ ] ++endif ++ ++if get_option('WITH_SANITY') ++ outputs += {'name' : 'SanityCheck', 'format' : 'sanitycheck'} ++endif ++ ++outputs_tgts = [] ++ ++foreach output : outputs ++ link_libs = [libmist] ++ deps = [] ++ base = files('mist_out.cpp') ++ tsBaseClass = 'Output' ++ extra_tgt_dep = [] ++ ++ sources = [ ++ files('output.cpp', ++ 'output_'+output.get('format')+'.cpp'), ++ io_cpp ++ ] ++ ++ if output.has_key('extra') ++ extra = output.get('extra') ++ if not extra.contains('debased') ++ sources += base ++ endif ++ if extra.contains('http') ++ sources += files('output_http.cpp') ++ if extra.contains('ts') ++ tsBaseClass = 'HTTPOutput' ++ endif ++ endif ++ if extra.contains('jpg') ++ extra_tgt_dep = embed_tgts ++ endif ++ if extra.contains('ts') ++ sources += files('output_ts_base.cpp') ++ endif ++ if extra.contains('with_rist') ++ deps += librist ++ endif ++ if extra.contains('with_srt') ++ link_libs += libmist_srt ++ deps += libsrt ++ endif ++ else ++ sources += base ++ endif ++ if output.get('name').contains('HTTPS') ++ deps += ssl_deps ++ endif ++ ++ executables += { ++ 'name': 'MistOut'+output.get('name'), ++ 'sources' : [ ++ sources, ++ extra_tgt_dep, ++ header_tgts ++ ], ++ 'link' : link_libs, ++ 'deps' : deps, ++ 'defines' : [ ++ string_opt.format('OUTPUTTYPE', 'output_'+output.get('format')+'.h'), ++ '-DTS_BASECLASS='+tsBaseClass ++ ] ++ } ++endforeach ++ ++executables += { ++ 'name' : 'MistOutHTTP', ++ 'sources' : [ ++ files( ++ 'mist_out.cpp', ++ 'output.cpp', ++ 'output_http.cpp', ++ 'output_http_internal.cpp', ++ ), ++ io_cpp, ++ header_tgts, ++ embed_tgts, ++ ], ++ 'link' : libmist, ++ 'defines' :[ ++ string_opt.format('OUTPUTTYPE', 'output_http_internal.h') ++ ], ++ 'deps' : [] ++} +diff --git a/src/process/meson.build b/src/process/meson.build +new file mode 100644 +index 00000000..d36e9fa9 +--- /dev/null ++++ b/src/process/meson.build +@@ -0,0 +1,50 @@ ++process_common = static_library('mist_process_common', ++ output_ebml_cpp, ++ input_ebml_cpp, ++ input_cpp, ++ output_http_cpp, ++ output_cpp, ++ io_cpp, ++ header_tgts, ++ include_directories: incroot, ++ install: false, ++) ++ ++executables += { ++ 'name' : 'MistProcFFMPEG', ++ 'sources' : [ ++ files('process_ffmpeg.cpp'), ++ header_tgts ++ ], ++ 'link' : [libmist, process_common], ++ 'deps' :[], ++ 'defines': [], ++} ++ ++executables += { ++ 'name' : 'MistProcMKVExec', ++ 'sources' : [ ++ files('process_exec.cpp'), ++ header_tgts ++ ], ++ 'link' : [libmist, process_common], ++ 'deps' :[], ++ 'defines': [], ++} ++ ++executables += { ++ 'name' : 'MistProcLivepeer', ++ 'sources' : [ ++ files('process_livepeer.cpp'), ++ input_cpp, ++ output_http_cpp, ++ output_ts_base_cpp, ++ output_cpp, ++ io_cpp, ++ header_tgts ++ ], ++ 'link' : [libmist], ++ 'deps' :[], ++ 'defines': [], ++} ++ +diff --git a/src/utils/meson.build b/src/utils/meson.build +new file mode 100644 +index 00000000..cd765f7f +--- /dev/null ++++ b/src/utils/meson.build +@@ -0,0 +1,28 @@ ++ ++utils = [ ++# {'name': 'Stats', 'file': 'stats'}, ++ {'name': 'META', 'file': 'meta'}, ++ {'name': 'RAX', 'file': 'rax'}, ++ {'name': 'AMF', 'file': 'amf'}, ++ {'name': 'Certbot', 'file': 'certbot'}, ++ {'name': 'Nuke', 'file': 'nuke'}, ++] ++ ++if get_option('LOAD_BALANCE') ++ utils += {'name': 'Load', 'file': 'load'} ++endif ++ ++utils_tgts = [] ++ ++foreach util : utils ++ executables += { ++ 'name': 'MistUtil'+util.get('name'), ++ 'sources' : [ ++ files('util_'+util.get('file')+'.cpp'), ++ header_tgts ++ ], ++ 'link' : libmist, ++ 'deps' : [], ++ 'defines' :[], ++ } ++endforeach +\ No newline at end of file +diff --git a/test/meson.build b/test/meson.build +new file mode 100644 +index 00000000..9b653992 +--- /dev/null ++++ b/test/meson.build +@@ -0,0 +1,18 @@ ++urltest = executable('urltest', 'url.cpp', include_directories: incroot, link_with: libmist) ++logtest = executable('logtest', 'log.cpp', include_directories: incroot, link_with: libmist) ++downloadertest = executable('downloadertest', 'downloader.cpp', include_directories: incroot, link_with: libmist) ++urireadertest = executable('urireadertest', 'urireader.cpp', include_directories: incroot, link_with: libmist, dependencies: ssl_deps) ++jsontest = executable('jsontest', 'json.cpp', include_directories: incroot, link_with: libmist) ++resolvetest = executable('resolvetest', 'resolve.cpp', include_directories: incroot, link_with: libmist, dependencies: ssl_deps) ++bitwritertest = executable('bitwritertest', 'bitwriter.cpp', include_directories: incroot, link_with: libmist) ++streamstatustest = executable('streamstatustest', 'status.cpp', include_directories: incroot, link_with: libmist) ++websockettest = executable('websockettest', 'websocket.cpp', include_directories: incroot, link_with: libmist) ++test('URLTest', urltest) ++test('LOGTest', logtest) ++test('DownloaderTest', downloadertest) ++test('URIReaderTest', urireadertest) ++test('JSONTest', jsontest) ++test('ResolveTest', resolvetest) ++test('BitWriterTest', bitwritertest) ++test('StreamStatusTest', streamstatustest) ++test('WebSocketTest', websockettest) +-- +2.25.1 + + +From 6950726ee52e134d781d637721bb8d2efc755b02 Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Tue, 20 Sep 2022 15:40:48 +0200 +Subject: [PATCH 33/38] Fix building with NOSSL + +--- + lib/websocket.cpp | 2 ++ + src/input/input.cpp | 7 +++++++ + src/input/input.h | 2 ++ + 3 files changed, 11 insertions(+) + +diff --git a/lib/websocket.cpp b/lib/websocket.cpp +index c82b4cba..11a4449e 100644 +--- a/lib/websocket.cpp ++++ b/lib/websocket.cpp +@@ -8,6 +8,7 @@ + #include "mbedtls/sha1.h" + #endif + ++#if SSL + // Takes the data from a Sec-WebSocket-Key header, and returns the corresponding data for a Sec-WebSocket-Accept header + static std::string calculateKeyAccept(std::string client_key){ + client_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +@@ -18,6 +19,7 @@ static std::string calculateKeyAccept(std::string client_key){ + mbedtls_sha1_finish(&ctx, outdata); + return Encodings::Base64::encode(std::string((const char *)outdata, 20)); + } ++#endif + + namespace HTTP{ + +diff --git a/src/input/input.cpp b/src/input/input.cpp +index 782dc4ef..5257184c 100644 +--- a/src/input/input.cpp ++++ b/src/input/input.cpp +@@ -1388,17 +1388,24 @@ namespace Mist{ + encryption = M.getEncryption(idx); + std::string encryptionKey = + Encodings::Hex::decode(encryption.substr(encryption.find(":") + 1)); ++#if SSL//FIXME!!! + aesCipher.setEncryptKey(encryptionKey.c_str()); ++#endif + } + if (encryption.substr(0, encryption.find('/')) == "CTR128"){ ++#if SSL + DTSC::Packet encPacket = aesCipher.encryptPacketCTR( + M, thisPacket, M.getIvec(idx) + M.getPartIndex(thisTime, idx), idx); + thisPacket = encPacket; ++#endif ++ + }else if (encryption.substr(0, encryption.find('/')) == "CBC128"){ + char ivec[] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Bit::htobll(ivec + 8, M.getIvec(idx) + M.getPartIndex(thisTime, idx)); ++#if SSL + DTSC::Packet encPacket = aesCipher.encryptPacketCBC(M, thisPacket, ivec, idx); + thisPacket = encPacket; ++#endif + } + }else{ + thisPacket = DTSC::Packet(thisPacket, idx); +diff --git a/src/input/input.h b/src/input/input.h +index ce7686c1..0565ece8 100644 +--- a/src/input/input.h ++++ b/src/input/input.h +@@ -83,7 +83,9 @@ namespace Mist{ + Comms::Users users; + size_t connectedUsers; + ++#if SSL + Encryption::AES aesCipher; ++#endif + + IPC::sharedPage streamStatus; + +-- +2.25.1 + + +From c16755d08509d26593e9816408de4ea5b477ace0 Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Tue, 20 Sep 2022 15:40:29 +0200 +Subject: [PATCH 34/38] Fix building against modern ffmpeg + +--- + src/input/input_av.cpp | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/input/input_av.cpp b/src/input/input_av.cpp +index aa7cd28c..ee05727d 100644 +--- a/src/input/input_av.cpp ++++ b/src/input/input_av.cpp +@@ -21,9 +21,16 @@ namespace Mist{ + capa["source_file"] = "$source"; + capa["priority"] = 1; + capa["codecs"].null(); ++#if (LIBAVFORMAT_VERSION_MAJOR < 59) + av_register_all(); +- AVCodec *cInfo = 0; ++#endif ++ const AVCodec *cInfo = 0; ++#if (LIBAVCODEC_VERSION_MAJOR < 59) + while ((cInfo = av_codec_next(cInfo)) != 0){ ++#else ++ void *i = 0; ++ while ((cInfo = av_codec_iterate(&i))) { ++#endif + if (cInfo->type == AVMEDIA_TYPE_VIDEO){capa["codecs"]["video"].append(cInfo->name);} + if (cInfo->type == AVMEDIA_TYPE_AUDIO){capa["codecs"]["audio"].append(cInfo->name);} + if (cInfo->type == AVMEDIA_TYPE_SUBTITLE){capa["codecs"]["subtitle"].append(cInfo->name);} +@@ -57,7 +64,9 @@ namespace Mist{ + // make sure all av inputs are registered properly, just in case + // the constructor already does this, but under windows it doesn't remember that it has. + // Very sad, that. We may need to get windows some medication for it. ++#if (LIBAVFORMAT_VERSION_MAJOR < 59) + av_register_all(); ++#endif + + // close any already open files + if (pFormatCtx){ +-- +2.25.1 + + +From c2bb6d3087b6a4919be0f42b503317309000c027 Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Fri, 23 Sep 2022 10:41:38 +0200 +Subject: [PATCH 35/38] Skip DIR and non files when gathering list of + executables + +--- + lib/config.cpp | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/lib/config.cpp b/lib/config.cpp +index 5e9ce11a..c88e89ab 100644 +--- a/lib/config.cpp ++++ b/lib/config.cpp +@@ -34,6 +34,7 @@ + #include <stdarg.h> // for va_list + #include <stdlib.h> + #include <sys/types.h> ++#include <sys/stat.h> + #include <unistd.h> + + bool Util::Config::is_active = false; +@@ -784,7 +785,14 @@ void Util::getMyExec(std::deque<std::string> &execs){ + do{ + errno = 0; + if ((dp = readdir(d))){ +- if (strncmp(dp->d_name, "Mist", 4) == 0){execs.push_back(dp->d_name);} ++ if (dp->d_type != DT_DIR && strncmp(dp->d_name, "Mist", 4) == 0){ ++ if (dp->d_type != DT_REG) { ++ struct stat st = {}; ++ stat(dp->d_name, &st); ++ if (!S_ISREG(st.st_mode)) ++ continue; ++ } ++ execs.push_back(dp->d_name);} + } + }while (dp != NULL); + closedir(d); +-- +2.25.1 + + +From 7e3f5f39e07d903bfbaa6845f787a49192ac912e Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Fri, 14 Oct 2022 11:02:47 +0200 +Subject: [PATCH 36/38] Fix building TSRist without SRT + +--- + src/input/input_tsrist.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/input/input_tsrist.cpp b/src/input/input_tsrist.cpp +index 33f1155e..e697ae77 100644 +--- a/src/input/input_tsrist.cpp ++++ b/src/input/input_tsrist.cpp +@@ -11,7 +11,6 @@ + #include <mist/flv_tag.h> + #include <mist/http_parser.h> + #include <mist/mp4_generic.h> +-#include <mist/socket_srt.h> + #include <mist/stream.h> + #include <mist/timing.h> + #include <mist/ts_packet.h> +-- +2.25.1 + + +From bfc869b5101a62399d5d3b329fce6ec3df21cfe6 Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Mon, 2 May 2022 15:24:02 +0200 +Subject: [PATCH 37/38] Upstream MBED-TLS integrated SRTP support, allow + building against it + +--- + lib/dtls_srtp_handshake.cpp | 69 ++++++++++++++++++++++++++++++++++++- + lib/dtls_srtp_handshake.h | 14 ++++++++ + lib/socket.h | 6 +++- + meson.build | 34 ++++++++++++++++++ + src/output/output_https.h | 4 +++ + 5 files changed, 125 insertions(+), 2 deletions(-) + +diff --git a/lib/dtls_srtp_handshake.cpp b/lib/dtls_srtp_handshake.cpp +index ea092d13..8c3fa1c9 100644 +--- a/lib/dtls_srtp_handshake.cpp ++++ b/lib/dtls_srtp_handshake.cpp +@@ -1,6 +1,7 @@ + #include "defines.h" + #include "dtls_srtp_handshake.h" + #include <algorithm> ++#include <mbedtls/ssl.h> + #include <string.h> + + /* Write mbedtls into a log file. */ +@@ -11,6 +12,30 @@ + + /* ----------------------------------------- */ + ++#if HAVE_UPSTREAM_MBEDTLS_SRTP ++int DTLSSRTPHandshake::dtlsExtractKeyData( void *p_expkey, ++ const unsigned char *ms, ++ const unsigned char *, ++ size_t, ++ size_t, ++ size_t, ++ const unsigned char client_random[32], ++ const unsigned char server_random[32], ++ mbedtls_tls_prf_types tls_prf_type ) ++{ ++ DTLSSRTPHandshake *handshake = static_cast<DTLSSRTPHandshake *>(p_expkey); ++ memcpy(handshake->master_secret, ms, sizeof(handshake->master_secret)); ++ memcpy(handshake->randbytes, client_random, 32); ++ memcpy(handshake->randbytes + 32, server_random, 32); ++ handshake->tls_prf_type = tls_prf_type; ++ return 0; ++} ++//It breaks if not defined outside of the function ++static mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80, ++ MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32, ++ MBEDTLS_TLS_SRTP_UNSET}; ++#endif ++ + static void print_mbedtls_error(int r); + static void print_mbedtls_debug_message(void *ctx, int level, const char *file, int line, const char *str); + static int on_mbedtls_wants_to_read(void *user, unsigned char *buf, +@@ -33,8 +58,10 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt *certificate, mbedtls_pk_context *p + int (*writeCallback)(const uint8_t *data, int *nbytes)){ + + int r = 0; ++#if !HAVE_UPSTREAM_MBEDTLS_SRTP + mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80, + MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32}; ++#endif + + if (!writeCallback){ + FAIL_MSG("No writeCallack function given."); +@@ -90,14 +117,22 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt *certificate, mbedtls_pk_context *p + mbedtls_debug_set_threshold(10); + + /* enable SRTP */ ++#if !HAVE_UPSTREAM_MBEDTLS_SRTP + r = mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles, + sizeof(srtp_profiles) / sizeof(srtp_profiles[0])); ++#else ++ r = mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles); ++#endif + if (0 != r){ + print_mbedtls_error(r); + r = -40; + goto error; + } + ++#if HAVE_UPSTREAM_MBEDTLS_SRTP ++ mbedtls_ssl_conf_export_keys_ext_cb( &ssl_conf, dtlsExtractKeyData, this); ++#endif ++ + /* cert certificate chain + key, so we can verify the client-hello signed data */ + r = mbedtls_ssl_conf_own_cert(&ssl_conf, cert, key); + if (0 != r){ +@@ -266,6 +301,7 @@ int DTLSSRTPHandshake::resetSession(){ + */ + int DTLSSRTPHandshake::extractKeyingMaterial(){ + ++#if !HAVE_UPSTREAM_MBEDTLS_SRTP + int r = 0; + uint8_t keying_material[MBEDTLS_DTLS_SRTP_MAX_KEY_MATERIAL_LENGTH] ={}; + size_t keying_material_len = sizeof(keying_material); +@@ -275,8 +311,14 @@ int DTLSSRTPHandshake::extractKeyingMaterial(){ + print_mbedtls_error(r); + return -1; + } +- ++#else ++ uint8_t keying_material[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH] ={}; ++ mbedtls_dtls_srtp_info info = {}; ++ info.chosen_dtls_srtp_profile = 999; ++ mbedtls_ssl_get_dtls_srtp_negotiation_result(&ssl_ctx, &info); ++#endif + /* @todo following code is for server mode only */ ++#if !HAVE_UPSTREAM_MBEDTLS_SRTP + mbedtls_ssl_srtp_profile srtp_profile = mbedtls_ssl_get_dtls_srtp_protection_profile(&ssl_ctx); + switch (srtp_profile){ + case MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80:{ +@@ -292,6 +334,31 @@ int DTLSSRTPHandshake::extractKeyingMaterial(){ + return -6; + } + } ++#else ++ if (mbedtls_ssl_tls_prf(tls_prf_type, master_secret, sizeof(master_secret), "EXTRACTOR-dtls_srtp", randbytes,sizeof( randbytes ), ++ keying_material, sizeof( keying_material )) != 0) { ++ ERROR_MSG("mbedtls_ssl_tls_prf failed to create keying_material"); ++ return -6; ++ } ++ switch (info.chosen_dtls_srtp_profile){ ++ case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:{ ++ cipher = "SRTP_AES128_CM_SHA1_80"; ++ break; ++ } ++ case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:{ ++ cipher = "SRTP_AES128_CM_SHA1_32"; ++ break; ++ } ++ case MBEDTLS_TLS_SRTP_UNSET: { ++ ERROR_MSG("Wasn't able to negotiate the use of DTLS-SRTP"); ++ return -6; ++ } ++ default:{ ++ ERROR_MSG("Unhandled SRTP profile: %hu, cannot extract keying material.", info.chosen_dtls_srtp_profile); ++ return -6; ++ } ++ } ++#endif + + remote_key.assign((char *)(&keying_material[0]) + 0, 16); + local_key.assign((char *)(&keying_material[0]) + 16, 16); +diff --git a/lib/dtls_srtp_handshake.h b/lib/dtls_srtp_handshake.h +index 7250167e..d93fc2f5 100644 +--- a/lib/dtls_srtp_handshake.h ++++ b/lib/dtls_srtp_handshake.h +@@ -40,6 +40,20 @@ private: + mbedtls_ssl_config ssl_conf; + mbedtls_ssl_cookie_ctx cookie_ctx; + mbedtls_timing_delay_context timer_ctx; ++#if HAVE_UPSTREAM_MBEDTLS_SRTP ++ unsigned char master_secret[48]; ++ unsigned char randbytes[64]; ++ mbedtls_tls_prf_types tls_prf_type; ++ static int dtlsExtractKeyData( void *p_expkey, ++ const unsigned char *ms, ++ const unsigned char *, ++ size_t, ++ size_t, ++ size_t, ++ const unsigned char client_random[32], ++ const unsigned char server_random[32], ++ mbedtls_tls_prf_types tls_prf_type ); ++#endif + + public: + int (*write_callback)(const uint8_t *data, int *nbytes); +diff --git a/lib/socket.h b/lib/socket.h +index b369ac84..85f20f99 100644 +--- a/lib/socket.h ++++ b/lib/socket.h +@@ -22,7 +22,11 @@ + #include "mbedtls/debug.h" + #include "mbedtls/entropy.h" + #include "mbedtls/error.h" +-#include "mbedtls/net.h" ++#if !HAVE_UPSTREAM_MBEDTLS_SRTP ++#include <mbedtls/net.h> ++#else ++#include "mbedtls/net_sockets.h" ++#endif + #include "mbedtls/ssl.h" + #endif + +diff --git a/meson.build b/meson.build +index 38bd29c3..964ed660 100644 +--- a/meson.build ++++ b/meson.build +@@ -116,6 +116,40 @@ if usessl + mbedcrypto = ccpp.find_library('mbedcrypto') + srtp2 = dependency('libsrtp2') + ssl_deps = [mbedtls, mbedx509, mbedcrypto, srtp2] ++ ++ ##This currently only works for MbedTLS < 3 ++ code_upstream = ''' ++ #include <mbedtls/ssl.h> ++ static mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80, ++ MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32, ++ MBEDTLS_TLS_SRTP_UNSET}; ++ static int test() ++ { ++ mbedtls_ssl_config ssl_conf; ++ mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles); ++ return 0; ++ } ++ ''' ++ code_ddvtech = ''' ++ #include <mbedtls/ssl.h> ++ mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80, ++ MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32}; ++ static int test() ++ { ++ mbedtls_ssl_config ssl_conf; ++ mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles, ++ sizeof(srtp_profiles) / sizeof(srtp_profiles[0])); ++ return 0; ++ } ++ ''' ++ have_upstream_mbedtls_srtp = ccpp.compiles(code_upstream, dependencies: ssl_deps, name: 'MbedTLS SRTP is upstream') ++ if not have_upstream_mbedtls_srtp ++ ddvtech_mbedtls = ccpp.compiles(code_ddvtech, dependencies: ssl_deps, name: 'MbedTLS SRTP is DDVTECH') ++ if not ddvtech_mbedtls ++ error('MbedTLS SRTP Support is required for SSL Build') ++ endif ++ endif ++ option_defines += int_opt.format('HAVE_UPSTREAM_MBEDTLS_SRTP', have_upstream_mbedtls_srtp.to_int()) + endif + + add_project_arguments(option_defines, language: 'cpp') +diff --git a/src/output/output_https.h b/src/output/output_https.h +index 386cd1f9..6d95e51c 100644 +--- a/src/output/output_https.h ++++ b/src/output/output_https.h +@@ -3,7 +3,11 @@ + #include <mbedtls/certs.h> + #include <mbedtls/ctr_drbg.h> + #include <mbedtls/entropy.h> ++#if !HAVE_UPSTREAM_MBEDTLS_SRTP + #include <mbedtls/net.h> ++#else ++#include <mbedtls/net_sockets.h> ++#endif + #include <mbedtls/ssl.h> + #include <mbedtls/timing.h> + #include <mbedtls/x509.h> +-- +2.25.1 + + +From 395d91254b8abec645ce44fbd225fbc41427a0f1 Mon Sep 17 00:00:00 2001 +From: Gijs Peskens <gijs@peskens.net> +Date: Fri, 23 Sep 2022 19:26:10 +0200 +Subject: [PATCH 38/38] MBED-TLS 3 compat + +--- + lib/certificate.cpp | 8 ++++++-- + lib/certificate.h | 8 +++++++- + lib/dtls_srtp_handshake.cpp | 36 ++++++++++++++++++++++++++++++------ + lib/dtls_srtp_handshake.h | 19 +++++++++++++++++-- + src/output/output_https.cpp | 4 ++++ + src/output/output_https.h | 4 ++++ + 6 files changed, 68 insertions(+), 11 deletions(-) + +diff --git a/lib/certificate.cpp b/lib/certificate.cpp +index b504d55a..cd6672e8 100644 +--- a/lib/certificate.cpp ++++ b/lib/certificate.cpp +@@ -6,12 +6,12 @@ + Certificate::Certificate(){ + mbedtls_pk_init(&key); + mbedtls_x509_crt_init(&cert); ++ mbedtls_ctr_drbg_init(&rand_ctx); + } + + int Certificate::init(const std::string &countryName, const std::string &organization, + const std::string &commonName){ + +- mbedtls_ctr_drbg_context rand_ctx ={}; + mbedtls_entropy_context entropy_ctx ={}; + mbedtls_x509write_cert write_cert ={}; + mbedtls_rsa_context *rsa_ctx; +@@ -48,7 +48,6 @@ int Certificate::init(const std::string &countryName, const std::string &organiz + } + + // initialize random number generator +- mbedtls_ctr_drbg_init(&rand_ctx); + mbedtls_entropy_init(&entropy_ctx); + r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx, + (const unsigned char *)personalisation, strlen(personalisation)); +@@ -204,6 +203,7 @@ error: + Certificate::~Certificate(){ + mbedtls_pk_free(&key); + mbedtls_x509_crt_free(&cert); ++ mbedtls_ctr_drbg_free(&rand_ctx); + } + + /// Loads a single file into the certificate. Returns true on success. +@@ -215,7 +215,11 @@ bool Certificate::loadCert(const std::string & certFile){ + /// Loads a single key. Returns true on success. + bool Certificate::loadKey(const std::string & keyFile){ + if (!keyFile.size()){return true;} ++#if MBEDTLS_VERSION_MAJOR > 2 ++ return mbedtls_pk_parse_keyfile(&key, keyFile.c_str(), NULL, mbedtls_ctr_drbg_random, &rand_ctx) == 0; ++#else + return mbedtls_pk_parse_keyfile(&key, keyFile.c_str(), 0) == 0; ++#endif + } + + /// Calculates SHA256 fingerprint over the loaded certificate(s) +diff --git a/lib/certificate.h b/lib/certificate.h +index a8ccf747..350fc665 100644 +--- a/lib/certificate.h ++++ b/lib/certificate.h +@@ -9,8 +9,12 @@ + communication. This certificate uses a 2048 bits RSA key. + + */ +- ++#include <mbedtls/version.h> ++#if MBEDTLS_VERSION_MAJOR > 2 ++#include <mbedtls/build_info.h> ++#else + #include <mbedtls/config.h> ++#endif + #include <mbedtls/ctr_drbg.h> + #include <mbedtls/entropy.h> + #include <mbedtls/error.h> +@@ -32,4 +36,6 @@ public: + public: + mbedtls_x509_crt cert; + mbedtls_pk_context key; /* key context, stores private and public key. */ ++private: ++ mbedtls_ctr_drbg_context rand_ctx; + }; +diff --git a/lib/dtls_srtp_handshake.cpp b/lib/dtls_srtp_handshake.cpp +index 8c3fa1c9..70c89066 100644 +--- a/lib/dtls_srtp_handshake.cpp ++++ b/lib/dtls_srtp_handshake.cpp +@@ -13,7 +13,16 @@ + /* ----------------------------------------- */ + + #if HAVE_UPSTREAM_MBEDTLS_SRTP +-int DTLSSRTPHandshake::dtlsExtractKeyData( void *p_expkey, ++#if MBEDTLS_VERSION_MAJOR > 2 ++void DTLSSRTPHandshake::dtlsExtractKeyData( void *user, ++ mbedtls_ssl_key_export_type type, ++ const unsigned char *ms, ++ size_t, ++ const unsigned char client_random[32], ++ const unsigned char server_random[32], ++ mbedtls_tls_prf_types tls_prf_type ) ++#else ++int DTLSSRTPHandshake::dtlsExtractKeyData( void *user, + const unsigned char *ms, + const unsigned char *, + size_t, +@@ -22,13 +31,16 @@ int DTLSSRTPHandshake::dtlsExtractKeyData( void *p_expkey, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ) ++#endif + { +- DTLSSRTPHandshake *handshake = static_cast<DTLSSRTPHandshake *>(p_expkey); ++ DTLSSRTPHandshake *handshake = static_cast<DTLSSRTPHandshake *>(user); + memcpy(handshake->master_secret, ms, sizeof(handshake->master_secret)); + memcpy(handshake->randbytes, client_random, 32); + memcpy(handshake->randbytes + 32, server_random, 32); + handshake->tls_prf_type = tls_prf_type; ++#if MBEDTLS_VERSION_MAJOR == 2 + return 0; ++#endif + } + //It breaks if not defined outside of the function + static mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80, +@@ -129,7 +141,7 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt *certificate, mbedtls_pk_context *p + goto error; + } + +-#if HAVE_UPSTREAM_MBEDTLS_SRTP ++#if HAVE_UPSTREAM_MBEDTLS_SRTP && MBEDTLS_VERSION_MAJOR == 2 + mbedtls_ssl_conf_export_keys_ext_cb( &ssl_conf, dtlsExtractKeyData, this); + #endif + +@@ -160,6 +172,10 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt *certificate, mbedtls_pk_context *p + goto error; + } + ++#if MBEDTLS_VERSION_MAJOR > 2 ++ mbedtls_ssl_set_export_keys_cb(&ssl_ctx, dtlsExtractKeyData, this); ++#endif ++ + /* set bio handlers */ + mbedtls_ssl_set_bio(&ssl_ctx, (void *)this, on_mbedtls_wants_to_write, on_mbedtls_wants_to_read, NULL); + +@@ -223,7 +239,11 @@ int DTLSSRTPHandshake::parse(const uint8_t *data, size_t nbytes){ + return -2; + } + ++#if MBEDTLS_VERSION_MAJOR > 2 ++ if (mbedtls_ssl_is_handshake_over(&ssl_ctx)) { ++#else + if (MBEDTLS_SSL_HANDSHAKE_OVER == ssl_ctx.state){ ++#endif + ERROR_MSG("Already finished the handshake."); + return -3; + } +@@ -314,7 +334,6 @@ int DTLSSRTPHandshake::extractKeyingMaterial(){ + #else + uint8_t keying_material[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH] ={}; + mbedtls_dtls_srtp_info info = {}; +- info.chosen_dtls_srtp_profile = 999; + mbedtls_ssl_get_dtls_srtp_negotiation_result(&ssl_ctx, &info); + #endif + /* @todo following code is for server mode only */ +@@ -340,7 +359,12 @@ int DTLSSRTPHandshake::extractKeyingMaterial(){ + ERROR_MSG("mbedtls_ssl_tls_prf failed to create keying_material"); + return -6; + } +- switch (info.chosen_dtls_srtp_profile){ ++#if MBEDTLS_VERSION_MAJOR > 2 ++ mbedtls_ssl_srtp_profile chosen_profile = info.private_chosen_dtls_srtp_profile; ++#else ++ mbedtls_ssl_srtp_profile chosen_profile = info.chosen_dtls_srtp_profile; ++#endif ++ switch (chosen_profile){ + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:{ + cipher = "SRTP_AES128_CM_SHA1_80"; + break; +@@ -354,7 +378,7 @@ int DTLSSRTPHandshake::extractKeyingMaterial(){ + return -6; + } + default:{ +- ERROR_MSG("Unhandled SRTP profile: %hu, cannot extract keying material.", info.chosen_dtls_srtp_profile); ++ ERROR_MSG("Unhandled SRTP profile: %hu, cannot extract keying material.", chosen_profile); + return -6; + } + } +diff --git a/lib/dtls_srtp_handshake.h b/lib/dtls_srtp_handshake.h +index d93fc2f5..f9e9d432 100644 +--- a/lib/dtls_srtp_handshake.h ++++ b/lib/dtls_srtp_handshake.h +@@ -1,8 +1,14 @@ + #pragma once + + #include <deque> ++#include <mbedtls/version.h> ++#if MBEDTLS_VERSION_MAJOR == 2 + #include <mbedtls/certs.h> + #include <mbedtls/config.h> ++#else ++#include <mbedtls/build_info.h> ++//#include <mbedtls/pk.h> ++#endif + #include <mbedtls/ctr_drbg.h> + #include <mbedtls/debug.h> + #include <mbedtls/entropy.h> +@@ -44,7 +50,16 @@ private: + unsigned char master_secret[48]; + unsigned char randbytes[64]; + mbedtls_tls_prf_types tls_prf_type; +- static int dtlsExtractKeyData( void *p_expkey, ++#if MBEDTLS_VERSION_MAJOR > 2 ++ static void dtlsExtractKeyData( void *user, ++ mbedtls_ssl_key_export_type type, ++ const unsigned char *ms, ++ size_t, ++ const unsigned char client_random[32], ++ const unsigned char server_random[32], ++ mbedtls_tls_prf_types tls_prf_type ); ++#else ++ static int dtlsExtractKeyData( void *user, + const unsigned char *ms, + const unsigned char *, + size_t, +@@ -54,7 +69,7 @@ private: + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ); + #endif +- ++#endif + public: + int (*write_callback)(const uint8_t *data, int *nbytes); + std::deque<uint8_t> buffer; /* Accessed from BIO callbback. We copy the bytes you pass into `parse()` into this +diff --git a/src/output/output_https.cpp b/src/output/output_https.cpp +index 59fa0bfd..f6fb0054 100644 +--- a/src/output/output_https.cpp ++++ b/src/output/output_https.cpp +@@ -239,7 +239,11 @@ namespace Mist{ + } + + // Read key from cmdline option ++#if MBEDTLS_VERSION_MAJOR > 2 ++ ret = mbedtls_pk_parse_keyfile(&pkey, config->getString("key").c_str(), NULL, mbedtls_ctr_drbg_random, &ctr_drbg); ++#else + ret = mbedtls_pk_parse_keyfile(&pkey, config->getString("key").c_str(), 0); ++#endif + if (ret != 0){ + FAIL_MSG("Could not load any keys from file: %s", config->getString("key").c_str()); + return; +diff --git a/src/output/output_https.h b/src/output/output_https.h +index 6d95e51c..e3811216 100644 +--- a/src/output/output_https.h ++++ b/src/output/output_https.h +@@ -1,6 +1,9 @@ + #pragma once + #include "output.h" ++#include <mbedtls/version.h> ++#if MBEDTLS_VERSION_MAJOR == 2 + #include <mbedtls/certs.h> ++#endif + #include <mbedtls/ctr_drbg.h> + #include <mbedtls/entropy.h> + #if !HAVE_UPSTREAM_MBEDTLS_SRTP +@@ -33,6 +36,7 @@ namespace Mist{ + static mbedtls_ssl_config sslConf; + static mbedtls_x509_crt srvcert; + static mbedtls_pk_context pkey; ++ + }; + }// namespace Mist + +-- +2.25.1 + diff --git a/legacy/mistserver/link-execinfo.patch b/legacy/mistserver/link-execinfo.patch new file mode 100644 index 000000000..ed5c088bc --- /dev/null +++ b/legacy/mistserver/link-execinfo.patch @@ -0,0 +1,11 @@ +diff -ur a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2022-02-11 00:15:16.610459631 +0000 ++++ b/CMakeLists.txt 2022-02-11 00:15:01.221072666 +0000 +@@ -191,6 +191,7 @@ + endif() + target_link_libraries(mist + -lpthread ++ -lexecinfo + ${LIBRT} + ) + if (NOT DEFINED NOSSL ) diff --git a/legacy/mistserver/mistserver.confd b/legacy/mistserver/mistserver.confd new file mode 100644 index 000000000..e0c085d5f --- /dev/null +++ b/legacy/mistserver/mistserver.confd @@ -0,0 +1,7 @@ +# Configuration for mistserver +# +# Config file location +#MIST_CONFIG=/etc/mistserver.conf + +# Log file location +#MIST_LOG=/var/log/mistserver.log diff --git a/legacy/mistserver/mistserver.initd b/legacy/mistserver/mistserver.initd new file mode 100755 index 000000000..9f2765c40 --- /dev/null +++ b/legacy/mistserver/mistserver.initd @@ -0,0 +1,29 @@ +#!/sbin/openrc-run + +description="MistServer multimedia streaming service" + +: ${MIST_CONFIG:=/etc/mistserver.conf} +: ${MIST_LOG:=/var/log/mistserver.log} + +depend() { + need net + use logger dns + after sshd firewall +} + +start() { + ebegin "Starting ${SVCNAME}" + start-stop-daemon --start \ + --pidfile ${PIDFILE} \ + --exec MistController \ + -- -L ${MIST_LOG} -c ${MIST_CONFIG} + eend $? +} + +stop() { + ebegin "Stopping ${SVCNAME}" + start-stop-daemon --stop \ + --pidfile ${PIDFILE} \ + --exec MistController + eend $? +} diff --git a/legacy/mistserver/mistserver.pre-install b/legacy/mistserver/mistserver.pre-install new file mode 100644 index 000000000..9ef5b5f2e --- /dev/null +++ b/legacy/mistserver/mistserver.pre-install @@ -0,0 +1,7 @@ +#!/bin/sh + +groupadd -r mistserver 2>/dev/null +useradd -c mistserver -s /sbin/nologin -g mistserver \ + -m -r mistserver 2>/dev/null + +exit 0 diff --git a/legacy/mkcfm/APKBUILD b/legacy/mkcfm/APKBUILD deleted file mode 100644 index ab4c152a3..000000000 --- a/legacy/mkcfm/APKBUILD +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=mkcfm -pkgver=1.0.1 -pkgrel=0 -pkgdesc="Utility for creating summaries of font metric files" -url="https://www.X.Org/" -arch="all" -license="MIT" -depends="" -makedepends="libfontenc-dev libfs-dev libx11-dev libxfont-dev" -subpackages="$pkgname-doc" -source="https://www.x.org/releases/individual/app/mkcfm-$pkgver.tar.gz - constise.patch - " - -prepare() { - cd "$builddir" - default_prepare - update_config_sub -} - -build() { - cd "$builddir" - ./configure \ - --build=$CBUILD \ - --host=$CHOST \ - --prefix=/usr \ - --sysconfdir=/etc \ - --mandir=/usr/share/man \ - --localstatedir=/var - make -} - -check() { - cd "$builddir" - make check -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -sha512sums="fabd9e2a711b960356178f9b52a2e720c4f33699c125dd82831d7e5a84f33dee230ff1d4c1a4019900fc190779f1c7770a775037c06a226723038e6440900fd2 mkcfm-1.0.1.tar.gz -6dffe376f23a18c536004df70788c2725098c5a8d068538a98be0e1fbcda93709ba7968c862095d5bb807be652978ba9fd5b3f097eb8dc88343ade0989dc3a83 constise.patch" diff --git a/legacy/mkcfm/constise.patch b/legacy/mkcfm/constise.patch deleted file mode 100644 index aff209ecf..000000000 --- a/legacy/mkcfm/constise.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- mkcfm-1.0.1/mkcfm.c.old 2005-12-08 17:54:40.000000000 +0000 -+++ mkcfm-1.0.1/mkcfm.c 2018-12-31 07:32:01.460000000 +0000 -@@ -194,7 +194,7 @@ - - - Atom --MakeAtom(char *p, unsigned len, int makeit) -+MakeAtom(const char *p, unsigned len, int makeit) - { - return *p; - } diff --git a/legacy/mkfontdir/APKBUILD b/legacy/mkfontdir/APKBUILD deleted file mode 100644 index 45629cd20..000000000 --- a/legacy/mkfontdir/APKBUILD +++ /dev/null @@ -1,41 +0,0 @@ -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=mkfontdir -pkgver=1.0.7 -pkgrel=3 -pkgdesc="Font file index utility from X.Org" -url="https://www.X.Org/" -arch="noarch" -license="X11 AND MIT" -depends="encodings mkfontscale" -makedepends="util-macros" -subpackages="$pkgname-doc" -triggers="$pkgname.trigger=/usr/share/fonts/* - $pkgname.trigger=/usr/share/fonts/X11/*" -source="https://www.X.Org/releases/individual/app/$pkgname-$pkgver.tar.bz2" - -prepare() { - cd "$builddir" - update_config_sub - default_prepare -} - -build() { - cd "$builddir" - ./configure \ - --build=$CBUILD \ - --host=$CHOST \ - --prefix=/usr - make -} - -check() { - cd "$builddir" - make check -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -sha512sums="96d1920565514f90621e18a87fb5a2db9e052d1bffc6552d9659e065a21e252ab98b4e62013755032b98ed6d8c3381eb75c3c8e02651766ee4791ca622dcef1f mkfontdir-1.0.7.tar.bz2" diff --git a/legacy/mkfontdir/mkfontdir.trigger b/legacy/mkfontdir/mkfontdir.trigger deleted file mode 100644 index 3024d71f1..000000000 --- a/legacy/mkfontdir/mkfontdir.trigger +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -for i in "$@"; do - mkfontdir -e "/usr/share/fonts/X11/encodings" -e "/usr/share/fonts/X11/encodings/large" -- "$i" -done - diff --git a/legacy/mozjs/0003-build-Fix-library-install-name-on-macOS.patch b/legacy/mozjs/0003-build-Fix-library-install-name-on-macOS.patch new file mode 100644 index 000000000..7d66d5aac --- /dev/null +++ b/legacy/mozjs/0003-build-Fix-library-install-name-on-macOS.patch @@ -0,0 +1,30 @@ +From fd8fc6e7b8760c961be7a3b9c6559d15f5ad008f Mon Sep 17 00:00:00 2001 +From: Philip Chimento <philip.chimento@gmail.com> +Date: Wed, 5 Jul 2017 22:44:18 -0700 +Subject: [PATCH 03/10] build: Fix library install name on macOS + +In order for the library to work under JHbuild, it has to have an install +name with an absolute path, since it will be installed in a shared +location. + +https://bugzilla.mozilla.org/show_bug.cgi?id=1379536 +--- + config/rules.mk | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/rules.mk b/config/rules.mk +index a21128cf..d88bada3 100644 +--- a/config/rules.mk ++++ b/config/rules.mk +@@ -352,7 +352,7 @@ else + ifdef MOZ_IOS + _LOADER_PATH := @rpath + else +-_LOADER_PATH := @executable_path ++_LOADER_PATH := $(abspath $(prefix))/lib + endif + EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module + endif +-- +2.13.0 + diff --git a/legacy/mozjs/0009-build-Include-configure-script-be-nicer-about-option.patch b/legacy/mozjs/0009-build-Include-configure-script-be-nicer-about-option.patch new file mode 100644 index 000000000..1a27b9ab5 --- /dev/null +++ b/legacy/mozjs/0009-build-Include-configure-script-be-nicer-about-option.patch @@ -0,0 +1,53 @@ +From 83374895c64a673acfc7a1898f134a04c1a45d15 Mon Sep 17 00:00:00 2001 +From: Philip Chimento <philip.chimento@gmail.com> +Date: Wed, 5 Jul 2017 22:57:09 -0700 +Subject: [PATCH 09/10] build: Include configure script, be nicer about options + +A configure script is not included in the SpiderMonkey tarball by +default. Also, we have to account for JHbuild passing extra unknown +options like --disable-Werror. + +https://bugzilla.mozilla.org/show_bug.cgi?id=1379540 + +MODIFIED by Ian Stakenvicius, to *not* attempt to overwrite the existing +js/src/configure that 'make-source-package.sh' apparently adds to the +tarball. + +--- + python/mozbuild/mozbuild/configure/__init__.py | 2 +- + python/mozbuild/mozbuild/configure/options.py | 6 +++++- + 2 files changed + +diff --git a/python/mozbuild/mozbuild/configure/__init__.py b/python/mozbuild/mozbuild/configure/__init__.py +index 0fe640ca..09b460d3 100644 +--- a/python/mozbuild/mozbuild/configure/__init__.py ++++ b/python/mozbuild/mozbuild/configure/__init__.py +@@ -356,7 +356,7 @@ class ConfigureSandbox(dict): + # All options should have been removed (handled) by now. + for arg in self._helper: + without_value = arg.split('=', 1)[0] +- raise InvalidOptionError('Unknown option: %s' % without_value) ++ print('Ignoring', without_value, ': Unknown option') + + # Run the execution queue + for func, args in self._execution_queue: +diff --git a/python/mozbuild/mozbuild/configure/options.py b/python/mozbuild/mozbuild/configure/options.py +index 4310c862..15bfe425 100644 +--- a/python/mozbuild/mozbuild/configure/options.py ++++ b/python/mozbuild/mozbuild/configure/options.py +@@ -402,7 +402,11 @@ class CommandLineHelper(object): + + def add(self, arg, origin='command-line', args=None): + assert origin != 'default' +- prefix, name, values = Option.split_option(arg) ++ try: ++ prefix, name, values = Option.split_option(arg) ++ except InvalidOptionError as e: ++ print('Ignoring', arg, ':', e) ++ return + if args is None: + args = self._extra_args + if args is self._extra_args and name in self._extra_args: +-- +2.13.0 + diff --git a/legacy/mozjs/1002_drop_build_id.patch b/legacy/mozjs/1002_drop_build_id.patch new file mode 100644 index 000000000..9f62abaea --- /dev/null +++ b/legacy/mozjs/1002_drop_build_id.patch @@ -0,0 +1,33 @@ +From: Jory A. Pratt <anarchy@gentoo.org> + +We must drop build id as it causes conflicts when merging +thunderbird/firefox/seamonkey on same system when using +splitdebug + +diff --git a/js/src/old-configure.in b/js/src/old-configure.in +--- a/js/src/old-configure.in ++++ b/js/src/old-configure.in +@@ -478,23 +478,16 @@ if test "$GNU_CC"; then + + AC_MSG_CHECKING([for -z relro option to ld]) + _SAVE_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-z,relro" + AC_TRY_LINK(,,AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no]) + LDFLAGS=$_SAVE_LDFLAGS) + +- AC_MSG_CHECKING([for --build-id option to ld]) +- _SAVE_LDFLAGS=$LDFLAGS +- LDFLAGS="$LDFLAGS -Wl,--build-id" +- AC_TRY_LINK(,,AC_MSG_RESULT([yes]), +- AC_MSG_RESULT([no]) +- LDFLAGS=$_SAVE_LDFLAGS) +- + _DEFINES_CFLAGS="-include $jsconfdefs -DMOZILLA_CLIENT" + _USE_CPP_INCLUDE_FLAG=1 + fi + + if test "$GNU_CXX"; then + _DEFINES_CXXFLAGS="-DMOZILLA_CLIENT -include $jsconfdefs" + _USE_CPP_INCLUDE_FLAG=1 + fi diff --git a/legacy/mozjs/1004_fix_pie_detection.patch b/legacy/mozjs/1004_fix_pie_detection.patch new file mode 100644 index 000000000..e24adf365 --- /dev/null +++ b/legacy/mozjs/1004_fix_pie_detection.patch @@ -0,0 +1,34 @@ +From: Jory A. Pratt <anarchy@gentoo.org> + +CFLAGS must contain -fPIC when checking the linker + +diff --git a/build/autoconf/compiler-opts.m4 b/build/autoconf/compiler-opts.m4 +--- a/build/autoconf/compiler-opts.m4 ++++ b/build/autoconf/compiler-opts.m4 +@@ -205,23 +205,26 @@ MOZ_PIE= + + MOZ_ARG_ENABLE_BOOL(pie, + [ --enable-pie Enable Position Independent Executables], + MOZ_PIE=1, + MOZ_PIE= ) + + if test "$GNU_CC$CLANG_CC" -a -n "$MOZ_PIE"; then + AC_MSG_CHECKING([for PIE support]) ++ _SAVE_CFLAGS=$CFLAGS ++ CFLAGS="$CFLAGS -fPIC" + _SAVE_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $DSO_PIC_CFLAGS -pie" + AC_TRY_LINK(,,AC_MSG_RESULT([yes]) + [MOZ_PROGRAM_LDFLAGS="$MOZ_PROGRAM_LDFLAGS -pie"], + AC_MSG_RESULT([no]) + AC_MSG_ERROR([--enable-pie requires PIE support from the linker.])) + LDFLAGS=$_SAVE_LDFLAGS ++ CFLAGS=$_SAVE_CFLAGS + fi + + AC_SUBST(MOZ_PROGRAM_LDFLAGS) + + dnl ASan assumes no symbols are being interposed, and when that happens, + dnl it's not happy with it. Unconveniently, since Firefox is exporting + dnl libffi symbols and Gtk+3 pulls system libffi via libwayland-client, + dnl system libffi interposes libffi symbols that ASan assumes are in diff --git a/legacy/mozjs/6006_musl_pthread_setname.patch b/legacy/mozjs/6006_musl_pthread_setname.patch new file mode 100644 index 000000000..213509ff7 --- /dev/null +++ b/legacy/mozjs/6006_musl_pthread_setname.patch @@ -0,0 +1,29 @@ +From: Jory A. Pratt <anarchy@gentoo.org> + +set pthread name for non glibc systems + +diff --git a/js/src/threading/posix/Thread.cpp b/js/src/threading/posix/Thread.cpp +--- a/js/src/threading/posix/Thread.cpp ++++ b/js/src/threading/posix/Thread.cpp +@@ -155,18 +155,20 @@ + int rv; + #ifdef XP_DARWIN + rv = pthread_setname_np(name); + #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) + pthread_set_name_np(pthread_self(), name); + rv = 0; + #elif defined(__NetBSD__) + rv = pthread_setname_np(pthread_self(), "%s", (void*)name); +-#else ++#elif defined(__GLIBC__) + rv = pthread_setname_np(pthread_self(), name); ++#else ++ rv = 0; + #endif + MOZ_RELEASE_ASSERT(!rv); + } + + void js::ThisThread::GetName(char* nameBuffer, size_t len) { + MOZ_RELEASE_ASSERT(len >= 16); + + int rv = -1; diff --git a/legacy/mozjs/APKBUILD b/legacy/mozjs/APKBUILD new file mode 100644 index 000000000..86c7c5c0c --- /dev/null +++ b/legacy/mozjs/APKBUILD @@ -0,0 +1,90 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=mozjs +pkgver=60.5.2 +pkgrel=0 +pkgdesc="Standalone JavaScript interpreter from Mozilla" +url="https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey" +arch="all" +license="NPL-1.1" +depends="" +depends_dev="$pkgname=$pkgver-r$pkgrel" +makedepends="autoconf2.13 icu-dev libffi-dev nspr-dev python3 cmd:which + zlib-dev + ncurses-dev openssl-dev" +subpackages="$pkgname-dev" +source="https://distfiles.adelielinux.org/source/mozilla/mozjs-$pkgver.tar.bz2 + https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tar.xz + 0003-build-Fix-library-install-name-on-macOS.patch + 0009-build-Include-configure-script-be-nicer-about-option.patch + 1002_drop_build_id.patch + 1004_fix_pie_detection.patch + 6006_musl_pthread_setname.patch + endian.patch + " +builddir="$srcdir/mozjs-$pkgver" + +unpack() { + default_unpack + [ -z $SKIP_PYTHON ] || return 0 + + msg "Killing all remaining hope for humanity and building Python 2..." + cd "$srcdir/Python-2.7.15" + [ -d ../python ] && rm -r ../python + # 19:39 <+solar> just make the firefox build process build its own py2 copy + # 20:03 <calvin> TheWilfox: there's always violence + ./configure --prefix="$srcdir/python" + make -j $JOBS + # 6 tests failed: + # test__locale test_os test_posix test_re test_strptime test_time + # make test + make -j $JOBS install +} + +prepare() { + default_prepare + cd "$builddir"/js/src + export PATH="$srcdir/python/bin:$PATH" + autoconf-2.13 old-configure.in >/dev/null + autoconf-2.13 +} + +build() { + cd "$builddir"/js/src/build + export PATH="$srcdir/python/bin:$PATH" + ../configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --disable-jemalloc \ + --disable-optimize \ + --enable-tests \ + --with-intl-api \ + --with-system-icu \ + --with-system-nspr \ + --with-system-zlib + MOZ_MAKE_FLAGS="$MAKEFLAGS" make +} + +check() { + cd "$builddir"/js/src/build + dist/bin/jsapi-tests +} + +package() { + cd "$builddir"/js/src/build + make DESTDIR="$pkgdir" install + + # no real point for 400 MB monster. + # if someone needs this, we can split it into -dev. + rm "$pkgdir"/usr/lib/libjs_static.ajs +} + +sha512sums="5fb73330e7803bdd524fbe7cfdf4e6b72e85d4b22b0c827400317b5d052d1088d36e558ceac376393089e9d03e658b24e69262851fc04a66bbcda47135423dc0 mozjs-60.5.2.tar.bz2 +27ea43eb45fc68f3d2469d5f07636e10801dee11635a430ec8ec922ed790bb426b072da94df885e4dfa1ea8b7a24f2f56dd92f9b0f51e162330f161216bd6de6 Python-2.7.15.tar.xz +8563264274c8b47c41fcce0b23d8d31467c60b4f1e6b37e14a390950f0d4c84be08919e0cf3578367ca1c76633201fc7d182c98a1efb57b17ce176a3e1ed5b0d 0003-build-Fix-library-install-name-on-macOS.patch +2556f3322c5bc39c1efbbbd19b6843cf69b63a0255e8e3617f58b229e75ac221b6cb57fce15452cd1f25498c66f29f588f38c10c175b82c6fe163faaa7e3e2b0 0009-build-Include-configure-script-be-nicer-about-option.patch +0882664005d65d491d4b3d0cd73a2163637730eff41a2ad3ae1ea4e855e8728b83d1bc42632901d717f947a11e6c1c42a33f5286b0adedda3111068ae1425259 1002_drop_build_id.patch +11cef339e8ba5d446d9fbb3947c6526294a3577025f21323cfd959707cbcc36f24535d5b68ea286220891de584ae6deef9408e838fc720af453062a179f22f42 1004_fix_pie_detection.patch +00cc3ea149ea8527393fa3995fcb6fa7af41fc79488c38df2bcd3326dbf43bcc83db509b6dbf2c9c8d68998ce2c1ab1f18c1c46584d9aeb63ddd2cf05b1ca1ce 6006_musl_pthread_setname.patch +363f1df1a78799783b4e9f887dc85d83ec83c6ec392aeacbd98dc89e543d0cd3b9d1964ce274142b44847a03c47f845cbf6fa7fa17a04b25bbaa37fc5d714730 endian.patch" diff --git a/legacy/mozjs/endian.patch b/legacy/mozjs/endian.patch new file mode 100644 index 000000000..1a04573ea --- /dev/null +++ b/legacy/mozjs/endian.patch @@ -0,0 +1,141 @@ +Bug 1488552 - Ensure proper running on 64-bit and 32-bit BE platforms. + +diff --git a/js/src/gc/RelocationOverlay.h b/js/src/gc/RelocationOverlay.h +--- a/js/src/gc/RelocationOverlay.h ++++ b/js/src/gc/RelocationOverlay.h +@@ -29,23 +29,34 @@ struct Cell; + * This structure overlays a Cell that has been moved and provides a way to find + * its new location. It's used during generational and compacting GC. + */ + class RelocationOverlay { + /* See comment in js/public/HeapAPI.h. */ + static const uint32_t Relocated = js::gc::Relocated; + ++#if MOZ_LITTLE_ENDIAN || JS_BITS_PER_WORD == 32 + /* +- * Keep the low 32 bits untouched. Use them to distinguish strings from ++ * Keep the first 32 bits untouched. Use them to distinguish strings from + * objects in the nursery. + */ + uint32_t preserve_; + + /* Set to Relocated when moved. */ + uint32_t magic_; ++#elif JS_BITS_PER_WORD == 64 ++ /* ++ * On big-endian, we need to reorder to keep preserve_ lined up with the ++ * low 32 bits of the aligned group_ pointer in JSObject. ++ */ ++ uint32_t magic_; ++ uint32_t preserve_; ++#else ++# error "Unknown endianness or word size" ++#endif + + /* The location |this| was moved to. */ + Cell* newLocation_; + + /* A list entry to track all relocated things. */ + RelocationOverlay* next_; + + public: +diff --git a/js/src/vm/StringType.h b/js/src/vm/StringType.h +--- a/js/src/vm/StringType.h ++++ b/js/src/vm/StringType.h +@@ -2,16 +2,17 @@ + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #ifndef vm_StringType_h + #define vm_StringType_h + ++#include "mozilla/EndianUtils.h" + #include "mozilla/MemoryReporting.h" + #include "mozilla/PodOperations.h" + #include "mozilla/Range.h" + + #include "jsapi.h" + #include "jsfriendapi.h" + + #include "builtin/String.h" +@@ -168,8 +168,20 @@ class JSString : public js::gc::Cell + struct Data { + union { + struct { ++#if MOZ_LITTLE_ENDIAN || JS_BITS_PER_WORD == 32 + uint32_t flags; /* JSString */ + uint32_t length; /* JSString */ ++#elif JS_BITS_PER_WORD == 64 ++ /* ++ * On big-endian, we need to reorder to keep flags lined up ++ * with the low 32 bits of the aligned group_ pointer in ++ * JSObject. ++ */ ++ uint32_t length; /* JSString */ ++ uint32_t flags; /* JSString */ ++#else ++# error "Unknown endianness or word size" ++#endif + }; + uintptr_t flattenData; /* JSRope (temporary while flattening) */ + } u1; +--- thunderbird-60.2.1/js/src/gc/Marking-inl.h.old 2018-10-01 14:51:12.000000000 +0000 ++++ thunderbird-60.2.1/js/src/gc/Marking-inl.h 2018-10-12 19:08:28.260000000 +0000 +@@ -92,13 +92,29 @@ + MOZ_ASSERT(!isForwarded()); + // The location of magic_ is important because it must never be valid to see + // the value Relocated there in a GC thing that has not been moved. ++#if MOZ_LITTLE_ENDIAN || JS_BITS_PER_WORD == 32 ++ // On 32-bit, the magic_ aliases with whatever comes after the first ++ // pointer; on little-endian 64-bit, the magic_ aliases with the ++ // 32 most significant bits of the pointer, which are the second half. + static_assert(offsetof(RelocationOverlay, magic_) == + offsetof(JSObject, group_) + sizeof(uint32_t), + "RelocationOverlay::magic_ is in the wrong location"); + static_assert(offsetof(RelocationOverlay, magic_) == + offsetof(js::Shape, base_) + sizeof(uint32_t), + "RelocationOverlay::magic_ is in the wrong location"); ++#elif JS_BITS_PER_WORD == 64 ++ // On big-endian 64-bit, the magic_ aliases with the 32 most ++ // significant bits of the pointer, but now that's the first half. ++ static_assert(offsetof(RelocationOverlay, magic_) == ++ offsetof(JSObject, group_), ++ "RelocationOverlay::magic_ is in the wrong location"); ++ static_assert(offsetof(RelocationOverlay, magic_) == ++ offsetof(js::Shape, base_), ++ "RelocationOverlay::magic_ is in the wrong location"); ++#else ++# error "Unknown endianness or word size" ++#endif + static_assert( + offsetof(RelocationOverlay, magic_) == offsetof(JSString, d.u1.length), + "RelocationOverlay::magic_ is in the wrong location"); + magic_ = Relocated; +--- thunderbird-60.2.1/js/src/jsfriendapi.h.old 2018-10-01 14:51:13.000000000 +0000 ++++ thunderbird-60.2.1/js/src/jsfriendapi.h 2018-10-12 19:12:06.190000000 +0000 +@@ -9,6 +9,7 @@ + + #include "mozilla/Atomics.h" + #include "mozilla/Casting.h" ++#include "mozilla/EndianUtils.h" + #include "mozilla/Maybe.h" + #include "mozilla/MemoryReporting.h" + #include "mozilla/UniquePtr.h" +@@ -640,8 +641,15 @@ + static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6); + static const uint32_t EXTERNAL_FLAGS = LINEAR_BIT | NON_ATOM_BIT | JS_BIT(5); + static const uint32_t TYPE_FLAGS_MASK = JS_BIT(6) - 1; ++#if MOZ_LITTLE_ENDIAN || JS_BITS_PER_WORD == 32 + uint32_t flags; + uint32_t length; ++#elif JS_BITS_PER_WORD == 64 ++ uint32_t length; ++ uint32_t flags; ++#else ++# error "Unknown endianness or word size" ++#endif + union { + const JS::Latin1Char* nonInlineCharsLatin1; + const char16_t* nonInlineCharsTwoByte; diff --git a/legacy/notmuch/0.28.2-disable-rpath.patch b/legacy/notmuch/0.28.2-disable-rpath.patch new file mode 100644 index 000000000..c7656bb3f --- /dev/null +++ b/legacy/notmuch/0.28.2-disable-rpath.patch @@ -0,0 +1,48 @@ +From ed15cac16414418c11896071d6ca9238d033f23d Mon Sep 17 00:00:00 2001 +From: Mira Ressel <aranea@aixah.de> +Date: Mon, 25 Feb 2019 08:18:24 +0100 +Subject: [PATCH] Add a configure flag to disable rpaths + +--- + configure | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index a6f5dfa2..5e7e5aa9 100755 +--- a/configure ++++ b/configure +@@ -82,6 +82,7 @@ WITH_API_DOCS=1 + WITH_EMACS=1 + WITH_DESKTOP=1 + WITH_BASH=1 ++WITH_RPATH=1 + WITH_RUBY=1 + WITH_ZSH=1 + WITH_RETRY_LOCK=1 +@@ -241,6 +242,14 @@ for option; do + fi + elif [ "${option}" = '--without-bash-completion' ] ; then + WITH_BASH=0 ++ elif [ "${option%%=*}" = '--with-rpath' ]; then ++ if [ "${option#*=}" = 'no' ]; then ++ WITH_RPATH=0 ++ else ++ WITH_RPATH=1 ++ fi ++ elif [ "${option}" = '--without-rpath' ] ; then ++ WITH_RPATH=0 + elif [ "${option%%=*}" = '--with-ruby' ]; then + if [ "${option#*=}" = 'no' ]; then + WITH_RUBY=0 +@@ -928,7 +937,7 @@ fi + rm -f compat/check_asctime + + printf "Checking for rpath support... " +-if ${CC} -Wl,--enable-new-dtags -Wl,-rpath,/tmp/ -o minimal minimal.c >/dev/null 2>&1 ++if [ $WITH_RPATH = "1" ] && ${CC} -Wl,--enable-new-dtags -Wl,-rpath,/tmp/ -o minimal minimal.c >/dev/null 2>&1 + then + printf "Yes.\n" + rpath_ldflags="-Wl,--enable-new-dtags -Wl,-rpath,\$(libdir)" +-- +2.19.2 + diff --git a/legacy/notmuch/APKBUILD b/legacy/notmuch/APKBUILD new file mode 100644 index 000000000..0eb168e2c --- /dev/null +++ b/legacy/notmuch/APKBUILD @@ -0,0 +1,96 @@ +# Contributor: Mira Ressel <aranea@aixah.de> +# Maintainer: +pkgname=notmuch +pkgver=0.28.4 +pkgrel=0 +pkgdesc="Thread-based email index, search and tagging" +url="https://notmuchmail.org/" +arch="all" +license="GPL-3.0+" +depends="" +depends_dev="gmime-dev talloc-dev xapian-core-dev zlib-dev" +makedepends="$depends_dev doxygen emacs python3-dev ruby-dev" +checkdepends="bash dtach gnupg" +subpackages="$pkgname-dev $pkgname-doc $pkgname-emacs py3-$pkgname:_py ruby-$pkgname:_rb $pkgname-bash-completion:bashcomp:noarch $pkgname-zsh-completion:zshcomp:noarch" +source="https://notmuchmail.org/releases/notmuch-$pkgver.tar.gz + 0.28.2-disable-rpath.patch" + +build() { + cd "$builddir" + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var \ + --without-bash-completion \ + --without-desktop \ + --without-rpath + make + + cd bindings/python + python3 setup.py build +} + +check() { + cd "$builddir" + # config, regexp-query: musl issues, TODO: Fixed in master + # atomicity, count, new, insert: gdb-based tests which fail randomly on some arches, with some CFLAGS, or during some moon phases + NOTMUCH_SKIP_TESTS="config regexp-query atomicity count new insert" make check +} + +package() { + cd "$builddir" + make DESTDIR="$pkgdir" install +} + +doc() { + default_doc + # TODO: We'd need sphinx to generate the man pages, but the raw *.rst's are still better than no docs at all. + mkdir -p "$subpkgdir/usr/share/doc/$pkgname" "$builddir/doc/man"* + cp -r "$builddir/doc/man"* "$subpkgdir/usr/share/doc/$pkgname/" +} + +emacs() { + mkdir -p "$subpkgdir/usr/bin" "$subpkgdir/usr/share" + mv "$pkgdir/usr/bin/notmuch-emacs-mua" "$subpkgdir/usr/bin" + mv "$pkgdir/usr/share/emacs" "$subpkgdir/usr/share" +} + +_py() { + pkgdesc="$pkgdesc (Python bindings)" + depends="$pkgname=$pkgver-r$pkgrel python3" + + cd "$builddir/bindings/python" + python3 setup.py install --prefix=/usr --root="$subpkgdir" +} + +_rb() { + pkgdesc="$pkgdesc (Ruby bindings)" + depends="$pkgname=$pkgver-r$pkgrel ruby" + + cd "$builddir/bindings/ruby" + make DESTDIR="$subpkgdir" install +} + + +bashcomp() { + pkgdesc="$pkgdesc (Bash completion)" + depends="" + install_if="$pkgname=$pkgver-r$pkgrel bash-completion" + + install -Dt "$subpkgdir/usr/share/bash-completion" "$builddir/completion/notmuch-completion.bash" +} + +zshcomp() { + pkgdesc="$pkgdesc (Zsh completion)" + depends="" + install_if="$pkgname=$pkgver-r$pkgrel zsh" + + mkdir -p "$subpkgdir/usr/share" + mv "$pkgdir/usr/share/zsh" "$subpkgdir/usr/share" +} + +sha512sums="77d7ad81e1f7dc93ae6392346da434f6dc74c21d19be728c2a6ca283c429f36e7081387d223af58eb5f63f5d2a8ad8367f0103f0bb9d052890c07fe419abbee7 notmuch-0.28.4.tar.gz +b2991ee5edf927f04d904d99888dbce17a98e9d4d7d809bc2248f45d214025f4a1632b19e4fbca2b08e99721ec8a7eea82384c5c718206884801c7bfa5a8c540 0.28.2-disable-rpath.patch" diff --git a/legacy/openjdk7/APKBUILD b/legacy/openjdk7/APKBUILD index e87060a19..291b38640 100644 --- a/legacy/openjdk7/APKBUILD +++ b/legacy/openjdk7/APKBUILD @@ -1,4 +1,4 @@ -# Contributor: Timo Teras <timo.teras@iki.fi> +# Contributor: Timo Teräs <timo.teras@iki.fi> # Contributor: Jakub Jirutka <jakub@jirutka.cz> # Maintainer: A. Wilcox <awilfox@adelielinux.org> pkgname=openjdk7 @@ -25,6 +25,7 @@ install="" # upstream binary versions RHINO_VER=1.7.7.2 +_RHINO_VER=1_7_7_2 ANT_VER=1.9.11 case $CARCH in @@ -50,6 +51,8 @@ _jrelib="$INSTALL_BASE/jre/lib/$_jarch" ldpath="$_jrelib:$_jrelib/native_threads:$_jrelib/headless:$_jrelib/server:$_jrelib/jli" sonameprefix="$pkgname:" +provides="$pkgname-bootstrap=$pkgver-r$pkgrel" + subpackages="$pkgname-jre-lib:jrelib:noarch $pkgname-jre $pkgname-jre-base:jrebase $pkgname-doc:doc" @@ -57,7 +60,7 @@ if [ "$BOOTSTRAP" != "no" ]; then makedepends="$makedepends java-gcj-compat" BOOTSTRAP_JAVA_HOME=/usr/lib/jvm/java-1.5-gcj/ else - makedepends="$makedepends $pkgname fastjar" + makedepends="$makedepends $pkgname-bootstrap fastjar" BOOTSTRAP_JAVA_HOME="$INSTALL_BASE" fi @@ -73,7 +76,7 @@ source="https://icedtea.classpath.org/download/source/icedtea-$_icedteaver.tar.g langtools-$_dropsver.tar.bz2::$_dropsurl/langtools.tar.bz2 hotspot-$_dropsver.tar.bz2::$_dropsurl/hotspot.tar.bz2 https://archive.apache.org/dist/ant/binaries/apache-ant-$ANT_VER-bin.tar.gz - https://github.com/mozilla/rhino/releases/download/Rhino${RHINO_VER//./_}_Release/rhino-$RHINO_VER.zip + https://github.com/mozilla/rhino/releases/download/Rhino${_RHINO_VER}_Release/rhino-$RHINO_VER.zip icedtea-hotspot-musl.patch icedtea-hotspot-musl-ppc.patch diff --git a/legacy/openjdk7/icedtea-jdk-no-lib-nsl-uclibc.patch b/legacy/openjdk7/icedtea-jdk-no-lib-nsl-uclibc.patch deleted file mode 100644 index 26f89bb54..000000000 --- a/legacy/openjdk7/icedtea-jdk-no-lib-nsl-uclibc.patch +++ /dev/null @@ -1,84 +0,0 @@ ---- openjdk.orig/hotspot/agent/src/os/solaris/dbx/Makefile -+++ openjdk/hotspot/agent/src/os/solaris/dbx/Makefile -@@ -50,7 +50,7 @@ - CFLAGS_32bit := -xarch=v8 - CFLAGS_64bit := -xarch=v9 - CFLAGS := -PIC -xO3 $(INCLUDES) --LIBS := -lsocket -lnsl -lrtld_db -+LIBS := -lsocket -lrtld_db - LDFLAGS := -G - - ifneq "$(ARCH)" "i486" ---- openjdk.orig/jdk/make/java/hpi/hpi_common.gmk -+++ openjdk/jdk/make/java/hpi/hpi_common.gmk -@@ -86,5 +86,5 @@ - # Things that must be linked in. - # - ifneq ($(PLATFORM), windows) --OTHER_LDLIBS += $(LIBSOCKET) -lnsl $(LIBM) -ldl -+OTHER_LDLIBS += $(LIBSOCKET) $(LIBM) -ldl - endif ---- openjdk.orig/jdk/make/java/java/Makefile -+++ openjdk/jdk/make/java/java/Makefile -@@ -205,7 +205,7 @@ - OTHER_LDLIBS += $(JVMLIB) -libpath:$(OBJDIR)/../../../fdlibm/$(OBJDIRNAME) fdlibm.lib \ - -libpath:$(OBJDIR)/../../../verify/$(OBJDIRNAME) verify.lib - else --OTHER_LDLIBS += $(JVMLIB) -lverify $(LIBSOCKET) -lnsl -ldl \ -+OTHER_LDLIBS += $(JVMLIB) -lverify $(LIBSOCKET) -ldl \ - -L$(OBJDIR)/../../../fdlibm/$(OBJDIRNAME) -lfdlibm.$(ARCH) - endif - ---- openjdk.orig/jdk/make/java/java_hprof_demo/Makefile -+++ openjdk/jdk/make/java/java_hprof_demo/Makefile -@@ -83,7 +83,7 @@ - ifeq ($(PLATFORM), windows) - OTHER_LDLIBS += wsock32.lib winmm.lib - else -- OTHER_LDLIBS += $(LIBSOCKET) -lnsl -ldl -+ OTHER_LDLIBS += $(LIBSOCKET) -ldl - endif - - # ---- openjdk.orig/jdk/make/java/net/Makefile -+++ openjdk/jdk/make/java/net/Makefile -@@ -97,7 +97,7 @@ - # Will not compile at warning level 3 if warnings are fatal - COMPILER_WARNINGS_FATAL=false - else -- OTHER_LDLIBS = $(LIBSOCKET) -lnsl -ldl $(JVMLIB) -+ OTHER_LDLIBS = $(LIBSOCKET) -ldl $(JVMLIB) - endif - ifeq ($(PLATFORM), linux) - OTHER_LDLIBS += -lpthread ---- openjdk.orig/jdk/make/jpda/transport/socket/Makefile -+++ openjdk/jdk/make/jpda/transport/socket/Makefile -@@ -42,11 +42,11 @@ - endif - - ifeq ($(PLATFORM), linux) -- OTHER_LDLIBS += -lnsl $(LIBSOCKET) -lpthread -+ OTHER_LDLIBS += $(LIBSOCKET) -lpthread - endif - - ifeq ($(PLATFORM), solaris) -- OTHER_LDLIBS += -lnsl $(LIBSOCKET) -+ OTHER_LDLIBS += $(LIBSOCKET) - endif - - ifeq ($(PLATFORM), windows) ---- openjdk.orig/jdk/make/mkdemo/jvmti/hprof/Makefile -+++ openjdk/jdk/make/mkdemo/jvmti/hprof/Makefile -@@ -39,10 +39,10 @@ - EXTRA_LIBS += wsock32.lib winmm.lib - endif - ifeq ($(PLATFORM), solaris) -- OTHER_LDLIBS += $(LIBSOCKET) -lnsl -ldl -+ OTHER_LDLIBS += $(LIBSOCKET) -ldl - endif - ifeq ($(PLATFORM), linux) -- OTHER_LDLIBS += $(LIBSOCKET) -lnsl -ldl -lpthread -+ OTHER_LDLIBS += $(LIBSOCKET) -ldl -lpthread - endif - - # diff --git a/legacy/perl-devel-mat-dumper/APKBUILD b/legacy/perl-devel-mat-dumper/APKBUILD new file mode 100644 index 000000000..3d0c927c4 --- /dev/null +++ b/legacy/perl-devel-mat-dumper/APKBUILD @@ -0,0 +1,34 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=perl-devel-mat-dumper +_pkgreal=Devel-MAT-Dumper +_author=PEVANS +_au=${_author%%"${_author#??}"} +_a=${_author%%"${_author#?}"} +pkgver=0.46 +pkgrel=0 +pkgdesc="Tool for writing a heap dump file for later analysis" +url="https://metacpan.org/pod/Devel::MAT" +arch="all" +license="GPL-1.0+ OR Artistic-1.0-Perl" +depends="perl" +makedepends="perl-dev perl-module-build" +subpackages="$pkgname-doc" +source="https://cpan.metacpan.org/authors/id/$_a/$_au/$_author/$_pkgreal-$pkgver.tar.gz" +builddir="$srcdir/$_pkgreal-$pkgver" + +build() { + perl Build.PL --destdir="$pkgdir" --prefix="/usr" --installdirs="vendor" + ./Build +} + +check() { + ./Build test +} + +package() { + ./Build install + find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete +} + +sha512sums="f012c1df3975429553eed998e897b5df31152f394a0080e923e9fe53a8e24304f3303addc2bf409f9ad64eca18f20e48fbf3c6e434a567bb41dbf47adb2a85f8 Devel-MAT-Dumper-0.46.tar.gz" diff --git a/legacy/perl-devel-mat/APKBUILD b/legacy/perl-devel-mat/APKBUILD new file mode 100644 index 000000000..841162da5 --- /dev/null +++ b/legacy/perl-devel-mat/APKBUILD @@ -0,0 +1,39 @@ +# Contributor: Síle Ekaterin Liszka <sheila@vulpine.house> +# Maintainer: Síle Ekaterin Liszka <sheila@vulpine.house> +pkgname=perl-devel-mat +_pkgreal=Devel-MAT +_author=PEVANS +_au=${_author%%"${_author#??}"} +_a=${_author%%"${_author#?}"} +pkgver=0.49 +pkgrel=0 +pkgdesc="Perl Memory Analysis Tool" +url="https://metacpan.org/pod/Devel::MAT" +arch="all" +license="GPL-1.0+ OR Artistic-1.0-Perl" +depends="perl" +checkdepends="perl-test-fatal perl-test-identity" +makedepends="perl-commandable perl-dev perl-devel-mat-dumper + perl-feature-compat-try perl-file-sharedir perl-heap perl-list-utilsby + perl-module-build perl-module-pluggable perl-string-tagged + perl-string-tagged-terminal perl-struct-dumb perl-syntax-keyword-match + perl-xs-parse-keyword" +subpackages="$pkgname-doc" +source="https://cpan.metacpan.org/authors/id/$_a/$_au/$_author/$_pkgreal-$pkgver.tar.gz" +builddir="$srcdir/$_pkgreal-$pkgver" + +build() { + perl Build.PL --destdir="$pkgdir" --prefix="/usr" --installdirs="vendor" + ./Build +} + +check() { + ./Build test +} + +package() { + ./Build install + find "$pkgdir" \( -name perllocal.pod -o -name .packlist \) -delete +} + +sha512sums="7940c5c87462da4dd953bbcd5fbd63fa924195489e290c241de597689f430fc1840b8cc0768fefbe896c97249a51286fd93b0afe0f95ad8acb68d73b9e46f50c Devel-MAT-0.49.tar.gz" diff --git a/legacy/smake/APKBUILD b/legacy/smake/APKBUILD deleted file mode 100644 index 809060c9b..000000000 --- a/legacy/smake/APKBUILD +++ /dev/null @@ -1,35 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=smake -pkgver=1.2.5 -pkgrel=0 -pkgdesc="Highly portable Unix make implementation" -url="https://sourceforge.net/projects/s-make/" -arch="all" -options="!check" # No test suite. -license="CDDL-1.0 AND GPL-2.0-only" -depends="" -makedepends="" -subpackages="$pkgname-doc" -source="https://download.sourceforge.net/s-make/smake-$pkgver.tar.bz2" - -prepare() { - cd "$builddir" - default_prepare - sed -i -e "s|opt/schily|usr|" \ - $(find ./ -type f -name \*.[0-9ch] -exec grep -l 'opt/schily' '{}' '+') -} - -build() { - cd "$builddir" - export MAKEFLAGS="" - make INS_BASE=/usr -} - -package() { - cd "$builddir" - export MAKEFLAGS="" - make INS_BASE=/usr DESTDIR="$pkgdir" install -} - -sha512sums="15131f57942d6ea611602afa1f3d3d3d1892b0e7f0f6e5b1ace7f69f1acb7bd09403b8c70e380204cff75512f5824daef81d59205d758c93f2583b40caa873a8 smake-1.2.5.tar.bz2" diff --git a/legacy/sox/APKBUILD b/legacy/sox/APKBUILD new file mode 100644 index 000000000..8e9fe9934 --- /dev/null +++ b/legacy/sox/APKBUILD @@ -0,0 +1,87 @@ +# Contributor: Łukasz Jendrysik <scadu@yandex.com> +# Maintainer: +pkgname=sox +pkgver=14.4.2 +pkgrel=2 +pkgdesc="Convert between various audio formats" +url="http://sox.sourceforge.net/" +arch="all" +options="!check" # No test suite. +license="GPL-2.0+ AND LGPL-2.1+ AND MIT AND BSD-1-Clause" +makedepends="alsa-lib-dev ffmpeg-dev file-dev flac-dev gsm-dev lame-dev + libao-dev libid3tag-dev libmad-dev libogg-dev libsamplerate-dev + libsndfile-dev libvorbis-dev opusfile-dev pulseaudio-dev + autoconf automake libtool" +depends="" +subpackages="$pkgname-dev $pkgname-doc" +source="https://downloads.sourceforge.net/sourceforge/$pkgname/$pkgname-$pkgver.tar.gz + CVE-2017-11332.patch + CVE-2017-11358.patch + CVE-2017-11359.patch + CVE-2017-15370.patch + CVE-2017-15371.patch + CVE-2017-15372.patch + CVE-2017-15642.patch + CVE-2017-18189.patch + CVE-2019-13590.patch + CVE-2019-8354.patch + CVE-2019-8355.patch + CVE-2019-8356.patch + CVE-2019-8357.patch + disable-pipe-file-detection.patch + " + +# secfixes: +# 14.4.2-r2: +# - CVE-2017-11332 +# - CVE-2017-11358 +# - CVE-2017-11359 +# - CVE-2017-15370 +# - CVE-2017-15371 +# - CVE-2017-15372 +# - CVE-2017-15642 +# - CVE-2017-18189 +# - CVE-2019-13590 +# - CVE-2019-8354 +# - CVE-2019-8355 +# - CVE-2019-8356 +# - CVE-2019-8357 + +prepare() { + default_prepare + autoreconf -vif +} + +build() { + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --with-dyn-default \ + --with-distro="${DISTRO_NAME:-Adélie Linux}" + make +} + +package() { + make DESTDIR="$pkgdir" install + ln -sf play "$pkgdir"/usr/bin/rec + ln -sf ../man1/sox.1.gz "$pkgdir"/usr/share/man/man7/soxeffect.7 + rm "$pkgdir"/usr/lib/sox/*.a +} + +sha512sums="b5c6203f4f5577503a034fe5b3d6a033ee97fe4d171c533933e2b036118a43a14f97c9668433229708609ccf9ee16abdeca3fc7501aa0aafe06baacbba537eca sox-14.4.2.tar.gz +b4bded0b15a2243fbb404a33fccf45ad5634d6c6e0f60b49b967592f00ff9bc3657ebcfa42b18a5af804e7f04a700773bece5951739b8206b2c68c46c9ec4c7f CVE-2017-11332.patch +28ffd5eef149563a1cdfcd920a89a0e2247ddbf4ed10a76c4e34ee57e3a30ec3a98bacf53fe1675da1431dd40c30b13cae0b9a1e26153c1aad6144322b7d78b0 CVE-2017-11358.patch +2c95d85f94877bf1637d2c1297944a77a8854506cad35b1c0d632237133cd970da82cded817696b19acde25b0e570f4c86659cc362a910e4ea76a037e3e56214 CVE-2017-11359.patch +bcbfd0785751372cd959a7419d88af24bb041dd02d3d0cf2f0dab46b6f6b55f284c1d823d20e5a0eae15191f3ccb2eefa2026287fdfbecb064722b006970ee00 CVE-2017-15370.patch +b116887f52eb4b70de9dda5f14e581579c4c1755c39100d88c4b8645bf9e053cfe87de3346eb138edc45fd2c36f0e1755f91e09511d279fe6d4661099c578420 CVE-2017-15371.patch +f8a4d38cfad80a50b9c758b222d83f6b51d96f1491862680e1632eec2a5c2a7c6f968660307f0f403e0b7537f7da19a510945648bdef8f1302fd4683be869581 CVE-2017-15372.patch +259980ea6fe08a2481a478a4a21b11a7fc4390b1b53023009d85fb2185ee63c42d2762e024af20912e7277688fac98e4eaa66b4a4e79840517ff2481ad50327e CVE-2017-15642.patch +de510114a9fbbbabe62149f3c22ebd1fae65ed68e6ed0b818f367bbee806c9e04be6db0c8e64f4985b7bd95dd0cc643e1475767fda4e405931f25104b4a2e39f CVE-2017-18189.patch +eab27e22035bdbe00d0dc4117f98bf9c5dcad4513a27e0e8a83506b94fca8055bc6ce532d24306aa8434942bef111b3511daf260df56fafb7b4ac5ed2075e3f7 CVE-2019-13590.patch +61342fad71dbe7f0ff10a7327eeed901c0defd5aafaace4ac755032ccf687d875856490c30f2af050823fd6ff1a1c7f503ae26670225eab916ab59fa857a8cb3 CVE-2019-8354.patch +3f05ab71680a67c9e8a4b33c70cb19a623f0925a2620ab007dc8d4a82caf5b73b50e3e5d40e242d6f65420d444b91e11bee09e4398e8079ca4af60bd34097593 CVE-2019-8355.patch +6eca5096c658a61939902a70d218b5662b663df84173d09d5b23f497bdcb81c04cd94d8debed2818079c342cec80ec29ff33d572611826bdbc12a5d465a20241 CVE-2019-8356.patch +82fbbf62a7124248ce74cf0daab0cd224a3da80e62923db58b8be31c4f145abe0e653f6968d0f6b862e5554d080d0f85b0bc0bcdb6dea34c130aa4ee9106d915 CVE-2019-8357.patch +eb90574a7c174a32ac77aa09a2bb4ebbea407463517e55943e16efd8b7c52393c6b7a6b2778d696f708627271f4d2212221a85fc50d2500b32143139a37a957a disable-pipe-file-detection.patch" diff --git a/legacy/sox/CVE-2017-11332.patch b/legacy/sox/CVE-2017-11332.patch new file mode 100644 index 000000000..511049d8e --- /dev/null +++ b/legacy/sox/CVE-2017-11332.patch @@ -0,0 +1,28 @@ +From 6e177c455fb554327ff8125b6e6dde1568610abe Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 5 Nov 2017 16:29:28 +0000 +Subject: [PATCH] wav: fix crash if channel count is zero (CVE-2017-11332) + +--- + src/wav.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/wav.c b/src/wav.c +index 5202556c..71fd52ac 100644 +--- a/src/wav.c ++++ b/src/wav.c +@@ -712,6 +712,11 @@ static int startread(sox_format_t * ft) + else + lsx_report("User options overriding channels read in .wav header"); + ++ if (ft->signal.channels == 0) { ++ lsx_fail_errno(ft, SOX_EHDR, "Channel count is zero"); ++ return SOX_EOF; ++ } ++ + if (ft->signal.rate == 0 || ft->signal.rate == dwSamplesPerSecond) + ft->signal.rate = dwSamplesPerSecond; + else +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-11358.patch b/legacy/sox/CVE-2017-11358.patch new file mode 100644 index 000000000..4fadeda30 --- /dev/null +++ b/legacy/sox/CVE-2017-11358.patch @@ -0,0 +1,44 @@ +From e410d00c4821726accfbe1f825f2def6376e181f Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 5 Nov 2017 16:43:35 +0000 +Subject: [PATCH] hcom: fix crash on input with corrupt dictionary + (CVE-2017-11358) + +--- + src/hcom.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/src/hcom.c b/src/hcom.c +index e76820e9..be17d9d2 100644 +--- a/src/hcom.c ++++ b/src/hcom.c +@@ -73,6 +73,14 @@ typedef struct { + size_t pos; /* Where next byte goes */ + } priv_t; + ++static int dictvalid(int n, int size, int left, int right) ++{ ++ if (n > 0 && left < 0) ++ return 1; ++ ++ return (unsigned)left < size && (unsigned)right < size; ++} ++ + static int startread(sox_format_t * ft) + { + priv_t *p = (priv_t *) ft->priv; +@@ -150,6 +158,11 @@ static int startread(sox_format_t * ft) + lsx_debug("%d %d", + p->dictionary[i].dict_leftson, + p->dictionary[i].dict_rightson); ++ if (!dictvalid(i, dictsize, p->dictionary[i].dict_leftson, ++ p->dictionary[i].dict_rightson)) { ++ lsx_fail_errno(ft, SOX_EHDR, "Invalid dictionary"); ++ return SOX_EOF; ++ } + } + rc = lsx_skipbytes(ft, (size_t) 1); /* skip pad byte */ + if (rc) +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-11359.patch b/legacy/sox/CVE-2017-11359.patch new file mode 100644 index 000000000..cb96c4a71 --- /dev/null +++ b/legacy/sox/CVE-2017-11359.patch @@ -0,0 +1,30 @@ +From 7b3f30e13e4845bafc93215a372c6eb7dcf04118 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 5 Nov 2017 17:02:11 +0000 +Subject: [PATCH] wav: fix crash writing header when channel count >64k + (CVE-2017-11359) + +--- + src/wav.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/wav.c b/src/wav.c +index 71fd52ac..eca1cde5 100644 +--- a/src/wav.c ++++ b/src/wav.c +@@ -1379,6 +1379,12 @@ static int wavwritehdr(sox_format_t * ft, int second_header) + long blocksWritten = 0; + sox_bool isExtensible = sox_false; /* WAVE_FORMAT_EXTENSIBLE? */ + ++ if (ft->signal.channels > UINT16_MAX) { ++ lsx_fail_errno(ft, SOX_EOF, "Too many channels (%u)", ++ ft->signal.channels); ++ return SOX_EOF; ++ } ++ + dwSamplesPerSecond = ft->signal.rate; + wChannels = ft->signal.channels; + wBitsPerSample = ft->encoding.bits_per_sample; +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-15370.patch b/legacy/sox/CVE-2017-15370.patch new file mode 100644 index 000000000..9e6a7f7ee --- /dev/null +++ b/legacy/sox/CVE-2017-15370.patch @@ -0,0 +1,28 @@ +From e076a7ad504add6e8c3b8699e8587eef0e0d9bc3 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 5 Nov 2017 16:21:23 +0000 +Subject: [PATCH] wav: ima_adpcm: fix buffer overflow on corrupt input + (CVE-2017-15370) + +Add the same check bad block size as was done for MS adpcm in commit +f39c574b ("More checks for invalid MS ADPCM blocks"). +--- + src/wav.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/wav.c b/src/wav.c +index eca1cde5..fad334cf 100644 +--- a/src/wav.c ++++ b/src/wav.c +@@ -127,7 +127,7 @@ static unsigned short ImaAdpcmReadBlock(sox_format_t * ft) + /* work with partial blocks. Specs say it should be null */ + /* padded but I guess this is better than trailing quiet. */ + samplesThisBlock = lsx_ima_samples_in((size_t)0, (size_t)ft->signal.channels, bytesRead, (size_t) 0); +- if (samplesThisBlock == 0) ++ if (samplesThisBlock == 0 || samplesThisBlock > wav->samplesPerBlock) + { + lsx_warn("Premature EOF on .wav input file"); + return 0; +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-15371.patch b/legacy/sox/CVE-2017-15371.patch new file mode 100644 index 000000000..7b38943f2 --- /dev/null +++ b/legacy/sox/CVE-2017-15371.patch @@ -0,0 +1,40 @@ +From 968c689ad2c4269a1a853434d99aa7ebf0c01354 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 5 Nov 2017 15:57:48 +0000 +Subject: [PATCH] flac: fix crash on corrupt metadata (CVE-2017-15371) + +--- + src/flac.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/flac.c b/src/flac.c +index 0d7829ec..07f45c1b 100644 +--- a/src/flac.c ++++ b/src/flac.c +@@ -119,9 +119,10 @@ static void decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FL + p->total_samples = metadata->data.stream_info.total_samples; + } + else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { ++ const FLAC__StreamMetadata_VorbisComment *vc = &metadata->data.vorbis_comment; + size_t i; + +- if (metadata->data.vorbis_comment.num_comments == 0) ++ if (vc->num_comments == 0) + return; + + if (ft->oob.comments != NULL) { +@@ -129,8 +130,9 @@ static void decoder_metadata_callback(FLAC__StreamDecoder const * const flac, FL + return; + } + +- for (i = 0; i < metadata->data.vorbis_comment.num_comments; ++i) +- sox_append_comment(&ft->oob.comments, (char const *) metadata->data.vorbis_comment.comments[i].entry); ++ for (i = 0; i < vc->num_comments; ++i) ++ if (vc->comments[i].entry) ++ sox_append_comment(&ft->oob.comments, (char const *) vc->comments[i].entry); + } + } + +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-15372.patch b/legacy/sox/CVE-2017-15372.patch new file mode 100644 index 000000000..dd7fcff5d --- /dev/null +++ b/legacy/sox/CVE-2017-15372.patch @@ -0,0 +1,100 @@ +From 515b986139183326cc40c67c75f83edc60826a9e Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 8 Nov 2017 00:27:46 +0000 +Subject: [PATCH] adpcm: fix stack overflow with >4 channels (CVE-2017-15372) + +--- + src/adpcm.c | 8 +++++++- + src/adpcm.h | 3 +++ + src/wav.c | 5 ++++- + 3 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/src/adpcm.c b/src/adpcm.c +index 2e13867e..f64b7d5c 100644 +--- a/src/adpcm.c ++++ b/src/adpcm.c +@@ -71,6 +71,11 @@ const short lsx_ms_adpcm_i_coef[7][2] = { + { 392,-232} + }; + ++extern void *lsx_ms_adpcm_alloc(unsigned chans) ++{ ++ return lsx_malloc(chans * sizeof(MsState_t)); ++} ++ + static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state, + sox_sample_t sample1, sox_sample_t sample2) + { +@@ -102,6 +107,7 @@ static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state, + + /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */ + const char *lsx_ms_adpcm_block_expand_i( ++ void *priv, + unsigned chans, /* total channels */ + int nCoef, + const short *coef, +@@ -113,7 +119,7 @@ const char *lsx_ms_adpcm_block_expand_i( + const unsigned char *ip; + unsigned ch; + const char *errmsg = NULL; +- MsState_t state[4]; /* One decompressor state for each channel */ ++ MsState_t *state = priv; /* One decompressor state for each channel */ + + /* Read the four-byte header for each channel */ + ip = ibuff; +diff --git a/src/adpcm.h b/src/adpcm.h +index af4d6f08..db5cc615 100644 +--- a/src/adpcm.h ++++ b/src/adpcm.h +@@ -29,8 +29,11 @@ + /* default coef sets */ + extern const short lsx_ms_adpcm_i_coef[7][2]; + ++extern void *lsx_ms_adpcm_alloc(unsigned chans); ++ + /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */ + extern const char *lsx_ms_adpcm_block_expand_i( ++ void *priv, + unsigned chans, /* total channels */ + int nCoef, + const short *coef, +diff --git a/src/wav.c b/src/wav.c +index fad334cf..066be6d7 100644 +--- a/src/wav.c ++++ b/src/wav.c +@@ -82,6 +82,7 @@ typedef struct { + /* following used by *ADPCM wav files */ + unsigned short nCoefs; /* ADPCM: number of coef sets */ + short *lsx_ms_adpcm_i_coefs; /* ADPCM: coef sets */ ++ void *ms_adpcm_data; /* Private data of adpcm decoder */ + unsigned char *packet; /* Temporary buffer for packets */ + short *samples; /* interleaved samples buffer */ + short *samplePtr; /* Pointer to current sample */ +@@ -175,7 +176,7 @@ static unsigned short AdpcmReadBlock(sox_format_t * ft) + } + } + +- errmsg = lsx_ms_adpcm_block_expand_i(ft->signal.channels, wav->nCoefs, wav->lsx_ms_adpcm_i_coefs, wav->packet, wav->samples, samplesThisBlock); ++ errmsg = lsx_ms_adpcm_block_expand_i(wav->ms_adpcm_data, ft->signal.channels, wav->nCoefs, wav->lsx_ms_adpcm_i_coefs, wav->packet, wav->samples, samplesThisBlock); + + if (errmsg) + lsx_warn("%s", errmsg); +@@ -791,6 +792,7 @@ static int startread(sox_format_t * ft) + + /* nCoefs, lsx_ms_adpcm_i_coefs used by adpcm.c */ + wav->lsx_ms_adpcm_i_coefs = lsx_malloc(wav->nCoefs * 2 * sizeof(short)); ++ wav->ms_adpcm_data = lsx_ms_adpcm_alloc(wChannels); + { + int i, errct=0; + for (i=0; len>=2 && i < 2*wav->nCoefs; i++) { +@@ -1216,6 +1218,7 @@ static int stopread(sox_format_t * ft) + free(wav->packet); + free(wav->samples); + free(wav->lsx_ms_adpcm_i_coefs); ++ free(wav->ms_adpcm_data); + free(wav->comment); + wav->comment = NULL; + +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-15642.patch b/legacy/sox/CVE-2017-15642.patch new file mode 100644 index 000000000..95beb4f6f --- /dev/null +++ b/legacy/sox/CVE-2017-15642.patch @@ -0,0 +1,34 @@ +From f56c0dbca8f5bd02ea88970c248c0d087386e807 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Mon, 20 Nov 2017 11:03:15 +0000 +Subject: [PATCH] aiff: fix crash on empty comment chunk (CVE-2017-15642) + +This fixes a use after free and double free if an empty comment +chunk follows a non-empty one. +--- + src/aiff.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/aiff.c b/src/aiff.c +index 240d2e1f..11ddb542 100644 +--- a/src/aiff.c ++++ b/src/aiff.c +@@ -62,7 +62,6 @@ int lsx_aiffstartread(sox_format_t * ft) + size_t ssndsize = 0; + char *annotation; + char *author; +- char *comment = NULL; + char *copyright; + char *nametext; + +@@ -270,6 +269,7 @@ int lsx_aiffstartread(sox_format_t * ft) + free(annotation); + } + else if (strncmp(buf, "COMT", (size_t)4) == 0) { ++ char *comment = NULL; + rc = commentChunk(&comment, "Comment:", ft); + if (rc) { + /* Fail already called in function */ +-- +2.25.0 + diff --git a/legacy/sox/CVE-2017-18189.patch b/legacy/sox/CVE-2017-18189.patch new file mode 100644 index 000000000..aa3791d01 --- /dev/null +++ b/legacy/sox/CVE-2017-18189.patch @@ -0,0 +1,33 @@ +From 09d7388c8ad5701ed9c59d1d600ff6154b066397 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Thu, 9 Nov 2017 11:45:10 +0000 +Subject: [PATCH] xa: validate channel count (CVE-2017-18189) + +A corrupt header specifying zero channels would send read_channels() +into an infinite loop. Prevent this by sanity checking the channel +count in open_read(). Also add an upper bound to prevent overflow +in multiplication. +--- + src/xa.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/xa.c b/src/xa.c +index 81a76772..9fc086ec 100644 +--- a/src/xa.c ++++ b/src/xa.c +@@ -143,6 +143,12 @@ static int startread(sox_format_t * ft) + lsx_report("User options overriding rate read in .xa header"); + } + ++ if (ft->signal.channels == 0 || ft->signal.channels > UINT16_MAX) { ++ lsx_fail_errno(ft, SOX_EFMT, "invalid channel count %d", ++ ft->signal.channels); ++ return SOX_EOF; ++ } ++ + /* Check for supported formats */ + if (ft->encoding.bits_per_sample != 16) { + lsx_fail_errno(ft, SOX_EFMT, "%d-bit sample resolution not supported.", +-- +2.25.0 + diff --git a/legacy/sox/CVE-2019-13590.patch b/legacy/sox/CVE-2019-13590.patch new file mode 100644 index 000000000..a09b11bae --- /dev/null +++ b/legacy/sox/CVE-2019-13590.patch @@ -0,0 +1,33 @@ +From 7b6a889217d62ed7e28188621403cc7542fd1f7e Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Tue, 4 Feb 2020 12:55:18 +0000 +Subject: [PATCH] sox-fmt: validate comments_bytes before use (CVE-2019-13590) + [bug #325] + +Cap the comments size to 1 GB to avoid overflows in subsequent +arithmetic. + +The missing null check mentioned in the bug report is bogus since +lsx_calloc() returns a valid pointer or aborts. +--- + src/sox-fmt.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/sox-fmt.c b/src/sox-fmt.c +index aad965cd..11c88771 100644 +--- a/src/sox-fmt.c ++++ b/src/sox-fmt.c +@@ -46,7 +46,9 @@ static int startread(sox_format_t * ft) + lsx_readdw(ft, &comments_bytes)) + return SOX_EOF; + +- if (((headers_bytes + 4) & 7) || headers_bytes < FIXED_HDR + comments_bytes || ++ if (((headers_bytes + 4) & 7) || ++ comments_bytes > 0x40000000 || /* max 1 GB */ ++ headers_bytes < FIXED_HDR + comments_bytes || + (num_channels > 65535)) /* Reserve top 16 bits */ { + lsx_fail_errno(ft, SOX_EHDR, "invalid sox file format header"); + return SOX_EOF; +-- +2.25.0 + diff --git a/legacy/sox/CVE-2019-8354.patch b/legacy/sox/CVE-2019-8354.patch new file mode 100644 index 000000000..1fa0e669f --- /dev/null +++ b/legacy/sox/CVE-2019-8354.patch @@ -0,0 +1,28 @@ +From f70911261a84333b077c29908e1242f69d7439eb Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 24 Apr 2019 14:57:34 +0100 +Subject: [PATCH] fix possible buffer size overflow in lsx_make_lpf() + (CVE-2019-8354) + +The multiplication in the size argument malloc() might overflow, +resulting in a small buffer being allocated. Use calloc() instead. +--- + src/effects_i_dsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/effects_i_dsp.c b/src/effects_i_dsp.c +index a979b501..e32dfa05 100644 +--- a/src/effects_i_dsp.c ++++ b/src/effects_i_dsp.c +@@ -357,7 +357,7 @@ double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, + double scale, sox_bool dc_norm) + { + int i, m = num_taps - 1; +- double * h = malloc(num_taps * sizeof(*h)), sum = 0; ++ double * h = calloc(num_taps, sizeof(*h)), sum = 0; + double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho); + assert(Fc >= 0 && Fc <= 1); + lsx_debug("make_lpf(n=%i Fc=%.7g β=%g ρ=%g dc-norm=%i scale=%g)", num_taps, Fc, beta, rho, dc_norm, scale); +-- +2.25.0 + diff --git a/legacy/sox/CVE-2019-8355.patch b/legacy/sox/CVE-2019-8355.patch new file mode 100644 index 000000000..d4d8cb808 --- /dev/null +++ b/legacy/sox/CVE-2019-8355.patch @@ -0,0 +1,59 @@ +Backport of the following: + +From ec073861aa9c0f779a3741c456e4f97d59366ffb Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Sun, 5 Nov 2017 15:40:16 +0000 +Subject: [PATCH] make: update exported symbol list [bug #266] + +From f8587e2d50dad72d40453ac1191c539ee9e50381 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 24 Apr 2019 17:39:45 +0100 +Subject: [PATCH] fix possible overflow in lsx_(re)valloc() size calculation + (CVE-2019-8355) + +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -95,7 +95,7 @@ libsox_la_LIBADD += @GOMP_LIBS@ + + libsox_la_CFLAGS = @WARN_CFLAGS@ + libsox_la_LDFLAGS = @APP_LDFLAGS@ -version-info @SHLIB_VERSION@ \ +- -export-symbols-regex '^(sox_.*|lsx_(check_read_params|(close|open)_dllibrary|(debug(_more|_most)?|fail|report|warn)_impl|eof|fail_errno|filelength|find_(enum_(text|value)|file_extension)|getopt(_init)?|lpc10_(create_(de|en)coder_state|(de|en)code)|raw(read|write)|read(_b_buf|buf|chars)|realloc|rewind|seeki|sigfigs3p?|strcasecmp|tell|unreadb|write(b|_b_buf|buf|s)))$$' ++ -export-symbols-regex '^(sox_.*|lsx_(([cm]|re)alloc.*|check_read_params|(close|open)_dllibrary|(debug(_more|_most)?|fail|report|warn)_impl|eof|error|fail_errno|filelength|find_(enum_(text|value)|file_extension)|flush|getopt(_init)?|lpc10_(create_(de|en)coder_state|(de|en)code)|raw(read|write)|read(_b_buf|buf|chars)|rewind|seeki|sigfigs3p?|strcasecmp|strdup|tell|unreadb|write(b|_b_buf|buf|s)))$$' + + if HAVE_WIN32_LTDL + libsox_la_SOURCES += win32-ltdl.c win32-ltdl.h +--- sox-14.4.2/src/xmalloc.c 2012-01-23 16:27:33.000000000 -0600 ++++ sox-14.4.2/src/xmalloc.c 2020-03-21 13:24:52.660007611 -0500 +@@ -41,3 +41,13 @@ void *lsx_realloc(void *ptr, size_t news + + return ptr; + } ++ ++void *lsx_realloc_array(void *p, size_t n, size_t size) ++{ ++ if (n > (size_t)-1 / size) { ++ lsx_fail("malloc size overflow"); ++ exit(2); ++ } ++ ++ return lsx_realloc(p, n * size); ++} +--- sox-14.4.2/src/xmalloc.h 2012-01-23 16:27:33.000000000 -0600 ++++ sox-14.4.2/src/xmalloc.h 2020-03-21 13:24:14.610007203 -0500 +@@ -23,12 +23,14 @@ + #include <stddef.h> + #include <string.h> + ++LSX_RETURN_VALID void *lsx_realloc_array(void *p, size_t n, size_t size); ++ + #define lsx_malloc(size) lsx_realloc(NULL, (size)) + #define lsx_calloc(n,s) (((n)*(s))? memset(lsx_malloc((n)*(s)),0,(n)*(s)) : NULL) + #define lsx_Calloc(v,n) v = lsx_calloc(n,sizeof(*(v))) + #define lsx_strdup(p) ((p)? strcpy((char *)lsx_malloc(strlen(p) + 1), p) : NULL) + #define lsx_memdup(p,s) ((p)? memcpy(lsx_malloc(s), p, s) : NULL) +-#define lsx_valloc(v,n) v = lsx_malloc((n)*sizeof(*(v))) +-#define lsx_revalloc(v,n) v = lsx_realloc(v, (n)*sizeof(*(v))) ++#define lsx_valloc(v,n) v = lsx_realloc_array(NULL, n, sizeof(*(v))) ++#define lsx_revalloc(v,n) v = lsx_realloc_array(v, n, sizeof(*(v))) + + #endif diff --git a/legacy/sox/CVE-2019-8356.patch b/legacy/sox/CVE-2019-8356.patch new file mode 100644 index 000000000..9375bc5ae --- /dev/null +++ b/legacy/sox/CVE-2019-8356.patch @@ -0,0 +1,92 @@ +From b7883ae1398499daaa926ae6621f088f0f531ed8 Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 24 Apr 2019 16:56:42 +0100 +Subject: [PATCH] fft4g: bail if size too large (CVE-2019-8356) + +Prevent overflowing of fixed-size buffers in bitrv2() and bitrv2conj() +if the transform size is too large. +--- + src/fft4g.c | 18 ++++++++++++++++++ + src/fft4g.h | 2 ++ + 2 files changed, 20 insertions(+) + +diff --git a/src/fft4g.c b/src/fft4g.c +index 38a8bcc0..88a2a7ec 100644 +--- a/src/fft4g.c ++++ b/src/fft4g.c +@@ -322,6 +322,9 @@ static void rftfsub(int n, double *a, int nc, double const *c); + + void cdft(int n, int isgn, double *a, int *ip, double *w) + { ++ if (n > FFT4G_MAX_SIZE) ++ return; ++ + if (n > (ip[0] << 2)) { + makewt(n >> 2, ip, w); + } +@@ -344,6 +347,9 @@ void rdft(int n, int isgn, double *a, int *ip, double *w) + int nw, nc; + double xi; + ++ if (n > FFT4G_MAX_SIZE) ++ return; ++ + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; +@@ -384,6 +390,9 @@ void ddct(int n, int isgn, double *a, int *ip, double *w) + int j, nw, nc; + double xr; + ++ if (n > FFT4G_MAX_SIZE) ++ return; ++ + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; +@@ -435,6 +444,9 @@ void ddst(int n, int isgn, double *a, int *ip, double *w) + int j, nw, nc; + double xr; + ++ if (n > FFT4G_MAX_SIZE) ++ return; ++ + nw = ip[0]; + if (n > (nw << 2)) { + nw = n >> 2; +@@ -486,6 +498,9 @@ void dfct(int n, double *a, double *t, int *ip, double *w) + int j, k, l, m, mh, nw, nc; + double xr, xi, yr, yi; + ++ if (n > FFT4G_MAX_SIZE) ++ return; ++ + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; +@@ -576,6 +591,9 @@ void dfst(int n, double *a, double *t, int *ip, double *w) + int j, k, l, m, mh, nw, nc; + double xr, xi, yr, yi; + ++ if (n > FFT4G_MAX_SIZE) ++ return; ++ + nw = ip[0]; + if (n > (nw << 3)) { + nw = n >> 3; +diff --git a/src/fft4g.h b/src/fft4g.h +index 2b8051ca..95ee3413 100644 +--- a/src/fft4g.h ++++ b/src/fft4g.h +@@ -13,6 +13,8 @@ + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#define FFT4G_MAX_SIZE 262144 ++ + void lsx_cdft(int, int, double *, int *, double *); + void lsx_rdft(int, int, double *, int *, double *); + void lsx_ddct(int, int, double *, int *, double *); +-- +2.25.0 + diff --git a/legacy/sox/CVE-2019-8357.patch b/legacy/sox/CVE-2019-8357.patch new file mode 100644 index 000000000..ec2b04d30 --- /dev/null +++ b/legacy/sox/CVE-2019-8357.patch @@ -0,0 +1,28 @@ +From 2ce02fea7b350de9ddfbcf542ba4dd59a8ab255b Mon Sep 17 00:00:00 2001 +From: Mans Rullgard <mans@mansr.com> +Date: Wed, 24 Apr 2019 15:08:51 +0100 +Subject: [PATCH] fix possible null pointer deref in lsx_make_lpf() + (CVE-2019-8357) + +If the buffer allocation fails, return NULL. +--- + src/effects_i_dsp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/effects_i_dsp.c b/src/effects_i_dsp.c +index e32dfa05..88b1b390 100644 +--- a/src/effects_i_dsp.c ++++ b/src/effects_i_dsp.c +@@ -362,6 +362,9 @@ double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, + assert(Fc >= 0 && Fc <= 1); + lsx_debug("make_lpf(n=%i Fc=%.7g β=%g ρ=%g dc-norm=%i scale=%g)", num_taps, Fc, beta, rho, dc_norm, scale); + ++ if (!h) ++ return NULL; ++ + for (i = 0; i <= m / 2; ++i) { + double z = i - .5 * m, x = z * M_PI, y = z * mult1; + h[i] = x? sin(Fc * x) / x : Fc; +-- +2.25.0 + diff --git a/legacy/sox/disable-pipe-file-detection.patch b/legacy/sox/disable-pipe-file-detection.patch new file mode 100644 index 000000000..3d2a854f7 --- /dev/null +++ b/legacy/sox/disable-pipe-file-detection.patch @@ -0,0 +1,11 @@ +--- sox-14.4.2/src/formats.c.old 2014-10-27 02:55:50.000000000 +0000 ++++ sox-14.4.2/src/formats.c 2018-07-22 04:36:34.380000000 +0000 +@@ -422,7 +422,7 @@ + /* To fix this #error, either simply remove the #error line and live without + * file-type detection with pipes, or add support for your compiler in the + * lines above. Test with cat monkey.wav | ./sox --info - */ +- #error FIX NEEDED HERE ++ /* #error FIX NEEDED HERE */ + #define NO_REWIND_PIPE + (void)fp; + #endif diff --git a/legacy/telegram/APKBUILD b/legacy/telegram/APKBUILD new file mode 100644 index 000000000..46cc4a9c1 --- /dev/null +++ b/legacy/telegram/APKBUILD @@ -0,0 +1,63 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=telegram +pkgver=2.0.1 +pkgrel=0 +pkgdesc="Telegram messaging app" +url="https://telegram.org/" +arch="all" +options="!check" # No test suite. +license="GPL-3.0-only WITH OpenSSL-exception" +depends="qt5-qtimageformats" +makedepends="cmake enchant-dev ffmpeg-dev hunspell-dev libdbusmenu-qt-dev + lz4-dev minizip-dev openal-soft-dev openssl-dev opus-dev pulseaudio-dev + python3 qt5-qtbase-dev range-v3 xxhash-dev xz-dev zlib-dev" +subpackages="" +source="https://github.com/telegramdesktop/tdesktop/releases/download/v$pkgver/tdesktop-$pkgver-full.tar.gz + endian.patch + " +builddir="$srcdir/tdesktop-$pkgver-full" + +build() { + [ -f "$HOME/telegram_credentials.sh" ] || die "You need to have a Telegram API ID." + + . $HOME/telegram_credentials.sh + + if [ "$CBUILD" != "$CHOST" ]; then + CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" + fi + # Can't use packaged rlottie, API mismatch. + cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DBUILD_SHARED_LIBS=True \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ + -DCMAKE_C_FLAGS="$CFLAGS" \ + -DDESKTOP_APP_DISABLE_CRASH_REPORTS=ON \ + -DDESKTOP_APP_USE_GLIBC_WRAPS=OFF \ + -DDESKTOP_APP_USE_PACKAGED_EXPECTED=OFF \ + -DDESKTOP_APP_USE_PACKAGED_GSL=OFF \ + -DDESKTOP_APP_USE_PACKAGED_RLOTTIE=OFF \ + -DDESKTOP_APP_USE_PACKAGED_VARIANT=OFF \ + -DTDESKTOP_API_ID="${TELEGRAM_API_ID}" \ + -DTDESKTOP_API_HASH="${TELEGRAM_API_HASH}" \ + -DTDESKTOP_DISABLE_GTK_INTEGRATION=ON \ + -DTDESKTOP_LAUNCHER_BASENAME=telegramdesktop \ + -DTDESKTOP_USE_PACKAGED_TGVOIP=OFF \ + -Ddisable_autoupdate=1 \ + ${CMAKE_CROSSOPTS} \ + . + make +} + +package() { + install -D -m755 "$builddir"/bin/telegram-desktop "$pkgdir"/usr/bin/telegram-desktop + install -D -m644 "$builddir"/lib/xdg/telegramdesktop.desktop "$pkgdir"/usr/share/applications/telegramdesktop.desktop + for _icon in 16 32 48 64 128 256 512; do + install -D -m644 "$builddir"/Telegram/Resources/art/icon$_icon.png \ + "$pkgdir"/usr/share/icons/hicolor/${_icon}x${_icon}/apps/telegram.png + done +} + +sha512sums="99cd7c5ca1e9dd75ecd98d272522b0e4aab2d46525e3d0c306503b7a00c9d25c1646e9d7462182682a58947c7435864af805a3b6f85906d8b21e5675cc8383cb tdesktop-2.0.1-full.tar.gz +c478bd59187493d60172d805ca19e9e09fa2c81b87d5dbbd5f3cd9aae0f207b463d127e06f2053f7b7b6ac00b3191d59e36ec6c5453a1da4d6535d1caad27242 endian.patch" diff --git a/legacy/telegram/endian.patch b/legacy/telegram/endian.patch new file mode 100644 index 000000000..40a3b4478 --- /dev/null +++ b/legacy/telegram/endian.patch @@ -0,0 +1,25 @@ +From d4c11502175e2a7821dbd92e029a90d54498e3e8 Mon Sep 17 00:00:00 2001 +From: John Zimmermann <johnz@posteo.net> +Date: Thu, 2 Jan 2020 12:57:33 +0100 +Subject: [PATCH] Build on big endian + +--- + Telegram/SourceFiles/config.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git Telegram/SourceFiles/config.h Telegram/SourceFiles/config.h +index fb7b54e4d..6a873fbd7 100644 +--- a/Telegram/SourceFiles/config.h ++++ b/Telegram/SourceFiles/config.h +@@ -162,7 +162,7 @@ constexpr auto ApiHash = "344583e45741c457fe1862106095a5eb"; + #endif // TDESKTOP_API_ID && TDESKTOP_API_HASH + + #if Q_BYTE_ORDER == Q_BIG_ENDIAN +-#error "Only little endian is supported!" ++#warning "Only little endian is supported!" + #endif // Q_BYTE_ORDER == Q_BIG_ENDIAN + + #if (TDESKTOP_ALPHA_VERSION != 0) +-- +2.24.1 + diff --git a/legacy/xbacklight/APKBUILD b/legacy/xbacklight/APKBUILD deleted file mode 100644 index 215baad9a..000000000 --- a/legacy/xbacklight/APKBUILD +++ /dev/null @@ -1,37 +0,0 @@ -# Contributor: A. Wilcox <awilfox@adelielinux.org> -# Maintainer: A. Wilcox <awilfox@adelielinux.org> -pkgname=xbacklight -pkgver=1.2.2 -pkgrel=0 -pkgdesc="X11 backlight brightness adjustment utility" -url="https://www.X.Org/" -arch="all" -license="MIT" -depends="!acpilight" # both provide /usr/bin/xbacklight -makedepends="util-macros xcb-util-dev" -subpackages="$pkgname-doc" -source="https://www.x.org/releases/individual/app/xbacklight-$pkgver.tar.bz2" - -build() { - cd "$builddir" - ./configure \ - --build=$CBUILD \ - --host=$CHOST \ - --prefix=/usr \ - --sysconfdir=/etc \ - --mandir=/usr/share/man \ - --localstatedir=/var - make -} - -check() { - cd "$builddir" - make check -} - -package() { - cd "$builddir" - make DESTDIR="$pkgdir" install -} - -sha512sums="4dca70ef8e3494b19ea126c46395807cddc007b2b09a133810daeb77ae27fa36ac4eec7813828248fc195abe27f59700cfa58ee65ef3a020a51f73e5107678ec xbacklight-1.2.2.tar.bz2" diff --git a/legacy/xf86-input-keyboard/APKBUILD b/legacy/xf86-input-keyboard/APKBUILD new file mode 100644 index 000000000..ab0182ece --- /dev/null +++ b/legacy/xf86-input-keyboard/APKBUILD @@ -0,0 +1,34 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=xf86-input-keyboard +pkgver=2.0.0 +pkgrel=0 +pkgdesc="X.Org keyboard driver" +url="https://www.X.Org/" +arch="all" +license="X11 AND MIT AND GPL-2.0-only" +depends="" +makedepends="util-macros xorgproto-dev xorg-server-dev" +subpackages="$pkgname-doc" +source="https://www.x.org/releases/individual/driver/$pkgname-$pkgver.tar.xz" + +build() { + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var + make +} + +check() { + make check +} + +package() { + make DESTDIR="$pkgdir" install +} + +sha512sums="8d53cdc3a9c9494896808e6a3974dcce5b2e7117bd9f5447240a01f126d3828a51143dbf4866ba94a761f83000f269026d7feda2a2b6c6d8a403b6cd46d5a437 xf86-input-keyboard-2.0.0.tar.xz" diff --git a/legacy/xf86-video-glint/APKBUILD b/legacy/xf86-video-glint/APKBUILD new file mode 100644 index 000000000..c3f2b0303 --- /dev/null +++ b/legacy/xf86-video-glint/APKBUILD @@ -0,0 +1,34 @@ +# Contributor: A. Wilcox <awilfox@adelielinux.org> +# Maintainer: A. Wilcox <awilfox@adelielinux.org> +pkgname=xf86-video-glint +pkgver=1.2.9 +pkgrel=0 +pkgdesc="X.Org driver for GLINT/Permedia GPUs" +url="https://www.X.Org/" +arch="all" +license="X11" +depends="" +makedepends="util-macros xorg-server-dev xorgproto-dev" +subpackages="$pkgname-doc" +source="https://www.X.Org/releases/individual/driver/xf86-video-glint-$pkgver.tar.bz2" + +build() { + ./configure \ + --build=$CBUILD \ + --host=$CHOST \ + --prefix=/usr \ + --sysconfdir=/etc \ + --mandir=/usr/share/man \ + --localstatedir=/var + make +} + +check() { + make check +} + +package() { + make DESTDIR="$pkgdir" install +} + +sha512sums="29b573abc2c77992562ab72ea99dfac5fa4baee99404747c53494680fe750b9c096833cd6c8013aa85f7fb5db5bdbee2a9b26dff633a6a4fe2dc8cd9f0adff12 xf86-video-glint-1.2.9.tar.bz2" |